All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure
@ 2014-03-20  9:39 Janani Venkataraman
  2014-03-20  9:39 ` [PATCH 01/33] Configure and Make files Janani Venkataraman
                   ` (34 more replies)
  0 siblings, 35 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Hi all,

The following series implements an infrastructure for capturing the core of an
application without disrupting its process.

Kernel Space Approach:

1) Posted an RFD to LKML explaining the various kernel-methods being analysed.

https://lkml.org/lkml/2013/9/3/122

2) Went ahead to implement the same using the task_work_add approach and posted an
RFC to LKML.

http://lwn.net/Articles/569534/

Based on the responses, the present approach implements the same in User-Space.

User Space Approach:

We didn't adopt the CRIU approach because our method would give us a head
start, as all that the distro would need is the PTRACE_functionality and nothing
more which is available from kernel versions 3.4 and above.

Basic Idea of User Space:

1) The threads are held using PTRACE_SEIZE and PTRACE_INTERRUPT.

2) The dump is then taken using the following:
    1) The register sets namely general purpose, floating point and the arch
    specific register sets are collected through PTRACE_GETREGSET calls by
    passing the appropriate register type as parameter.
    2) The virtual memory maps are collected from /proc/pid/maps.
    3) The auxiliary vector is collected from /proc/pid/auxv.
    4) Process state information for filling the notes such as PRSTATUS and
    PRPSINFO are collected from /proc/pid/stat and /proc/pid/status.
    5) The actual memory is read through process_vm_readv syscall as suggested
    by Andi Kleen.
    6) Command line arguments are collected from /proc/pid/cmdline

3) The threads are then released using PTRACE_DETACH.

Self Dump:

A self dump is implemented with the following approach which was adapted
from CRIU:

Gencore Daemon

The programs can request a dump using gencore() API, provided through
libgencore. This is implemented through a daemon which listens on a UNIX File
socket. The daemon is started immediately post installation.

We have provided service scripts for integration with systemd.

NOTE:

On systems with systemd, we could make use of socket option, which will avoid
the need for running the gencore daemon always. The systemd can wait on the
socket for requests and trigger the daemon as and when required. However, since
the systemd socket APIs are not exported yet, we have disabled the supporting
code for this feature.

libgencore:

1) The client interface is a standard library call. All that the dump requester
does is open the library and call the gencore() API and the dump will be
generated in the path specified(relative/absolute).

To Do:

1) Presently we wait indefinitely for the all the threads to seize. We can add
a time-out to decide how much time we need to wait for the threads to be
seized. This can be passed as command line argument in the case of a third
party dump and in the case of the self-dump through the library call. We need
to work on how much time to wait.

2) Like mentioned before, the systemd socket APIs are not exported yet and
hence this option is disabled now. Once these API's are available we can enable
the socket option.

We would like to push this to one of the following packages:
a) util-linux
b) coreutils
c) procps-ng

We are not sure which one would suit this application the best.
Please let us know your views on the same.

Patches 1 - 16 implements the dump generation.

Patches 17 - 24 implements the daemon approach.

Patch 25 implements the systemd socket approach.

Patches 26-27 implements the client-interface library.

Patches 28-33 handles the building and other packaging aspects.

Please let us know your reviews and comments.

Thanks.

Janani Venkataraman (33):
      Configure and Make files
      Validity of arguments
      Process Status
      Hold threads
      Fetching Memory maps
      Check ELF class
      Do elf_coredump
      Fills elf header
      Adding notes infrastructure
      Populates PRPS info
      Populate AUXV
      Fetch File maps
      Fetching thread specific Notes
      Populating Program Headers
      Updating Offset
      Writing to core file
      Daemonizing the Process
      Socket operations
      Block till request
      Handling Requests
      Get Clients PID
      Dump the task
      Handling SIG TERM of the daemon
      Handling SIG TERM of the child
      Systemd Socket ID retrieval
      [libgencore] Setting up Connection
      [libgencore] Request for dump
      Man pages
      Automake files for the doc folder
      README, COPYING, Changelog
      Spec file
      Socket and Service files.
      Support check


 COPYING            |   24 ++
 COPYING.LIBGENCORE |   24 ++
 Changelog          |    7 
 Makefile.am        |   22 +
 README             |  108 +++++++
 configure.ac       |    8 +
 doc/Makefile.am    |    2 
 doc/gencore.1      |   31 ++
 doc/gencore.3      |   28 ++
 gencore.service    |    9 +
 gencore.socket     |   10 +
 gencore.spec.in    |   88 ++++++
 gencore@.service   |    9 +
 libgencore.pc.in   |    8 +
 src/Makefile.am    |   13 +
 src/client.c       |  121 ++++++++
 src/coredump.c     |  764 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/coredump.h     |   74 +++++
 src/elf-compat.h   |  124 ++++++++
 src/elf.c          |  827 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/elf32.c        |   43 +++
 src/elf64.c        |   44 +++
 src/gencore.h      |    1 
 src/proc.c         |  278 +++++++++++++++++
 24 files changed, 2667 insertions(+)
 create mode 100644 COPYING
 create mode 100644 COPYING.LIBGENCORE
 create mode 100644 Changelog
 create mode 100644 README
 create mode 100644 doc/Makefile.am
 create mode 100644 doc/gencore.1
 create mode 100644 doc/gencore.3
 create mode 100644 gencore.service
 create mode 100644 gencore.socket
 create mode 100644 gencore.spec.in
 create mode 100644 gencore@.service
 create mode 100644 libgencore.pc.in
 create mode 100644 src/Makefile.am
 create mode 100644 src/client.c
 create mode 100644 src/coredump.c
 create mode 100644 src/coredump.h
 create mode 100644 src/elf-compat.h
 create mode 100644 src/elf.c
 create mode 100644 src/elf32.c
 create mode 100644 src/elf64.c
 create mode 100644 src/gencore.h
 create mode 100644 src/proc.c

-- 
Janani


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 01/33] Configure and Make files
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
@ 2014-03-20  9:39 ` Janani Venkataraman
  2014-03-20  9:39 ` [PATCH 02/33] Validity of arguments Janani Venkataraman
                   ` (33 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

configure.ac and automake files for the repository.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 Makefile.am  |    2 ++
 configure.ac |    7 +++++++
 2 files changed, 9 insertions(+)

diff --git a/Makefile.am b/Makefile.am
index e69de29..2cc6dc7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -0,0 +1,2 @@
+AUTOMAKE_OPTIONS = foreign
+SUBDIRS =
diff --git a/configure.ac b/configure.ac
index e69de29..f34a0c3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -0,0 +1,7 @@
+AC_INIT([Gencore], [0.1], [jananive@linux.vnet.ibm.com], [gencore], [])
+LT_INIT()
+AM_INIT_AUTOMAKE([-Wall -Werror foreign])
+AC_CONFIG_HEADERS([config.h])
+AC_PROG_CC
+AC_CONFIG_FILES(Makefile)
+AC_OUTPUT()


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 02/33] Validity of arguments
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
  2014-03-20  9:39 ` [PATCH 01/33] Configure and Make files Janani Venkataraman
@ 2014-03-20  9:39 ` Janani Venkataraman
  2014-03-20  9:39 ` [PATCH 03/33] Process Status Janani Venkataraman
                   ` (32 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

The validity of the arguments passed to the program are checked. PID is a
mandatory argument. The core file name is optional, if not specified the
default file name is core.pid.

If a self dump is requested then, the application is called with a --daemon
option or the --socket option.

If the SYSTEMD_SOCKET_OPTION is enabled, then the socket option will be fully
functional. The system where the program is run needs to have sd-daemon.h. For
this we need to have the correct version of systemd which has this socket
option enabled.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 Makefile.am     |    2 +
 configure.ac    |    2 +
 src/Makefile.am |    7 ++++
 src/coredump.c  |  104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 113 insertions(+), 2 deletions(-)
 create mode 100644 src/Makefile.am
 create mode 100644 src/coredump.c

diff --git a/Makefile.am b/Makefile.am
index 2cc6dc7..dfa49b2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,2 +1,2 @@
 AUTOMAKE_OPTIONS = foreign
-SUBDIRS =
+SUBDIRS = src
diff --git a/configure.ac b/configure.ac
index f34a0c3..8c785cd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,4 +4,4 @@ AM_INIT_AUTOMAKE([-Wall -Werror foreign])
 AC_CONFIG_HEADERS([config.h])
 AC_PROG_CC
 AC_CONFIG_FILES(Makefile)
-AC_OUTPUT()
+AC_OUTPUT(src/Makefile)
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..f7b25fa
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,7 @@
+AUTOMAKE_OPTIONS = foreign
+HAVE_SYSTEMD_SOCKET_SUPPORT = 0
+CFLAGS += -I. -DHAVE_SYSTEMD_SOCKET_SUPPORT='$(HAVE_SYSTEMD_SOCKET_SUPPORT)'
+
+bin_PROGRAMS = gencore
+gencore_SOURCES = coredump.c
+
diff --git a/src/coredump.c b/src/coredump.c
new file mode 100644
index 0000000..7a7fe11
--- /dev/null
+++ b/src/coredump.c
@@ -0,0 +1,104 @@
+/*
+ * Initiates the core-dump
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2013, 2014
+ *
+ * Authors:
+ *      Janani Venkataraman <jananve@in.ibm.com>
+ *      Suzuki K. Poulose <suzuki@in.ibm.com>
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* For logging all the messages */
+FILE *fp_log;
+
+/* Logging messages */
+void gencore_log(char *fmt, ...)
+{
+	va_list argptr;
+	va_start(argptr, fmt);
+	vfprintf(fp_log, fmt, argptr);
+	va_end(argptr);
+}
+
+/* Performs the core dump */
+int do_coredump(int pid, char *core_file)
+{
+	return 0;
+}
+
+/* Daemon for self dump */
+int daemon_dump(void)
+{
+	return 0;
+}
+
+#if HAVE_SYSTEMD_SOCKET_SUPPORT
+/* Systemd socket for self dump */
+int socket_dump(void)
+{
+	return 0;
+}
+#endif
+
+int main(int argc, char *argv[])
+{
+	int ret;
+	int pid;
+	char core_file[15];
+
+	if (argc < 2 || argc > 3) {
+		fprintf(stderr, "Invalid number of arguments.\n\n");
+		fprintf(stderr, "Usage: %s pid [output-file-name]\n", argv[0]);
+		return -1;
+	}
+
+	if (strcmp(argv[1], "--daemon") == 0)
+		ret = daemon_dump();
+#if HAVE_SYSTEMD_SOCKET_SUPPORT
+	else if (strcmp(argv[1], "--socket") == 0) {
+		fp_log = stderr;
+		ret = socket_dump();
+	}
+#endif
+	else if (strcmp(argv[1], "--help") == 0) {
+		printf("Usage: %s pid [output-file-name]\n", argv[0]);
+		return -1;
+	} else {
+		fp_log = stderr;
+		pid = atoi(argv[1]);
+		if (pid == 0 && argv[1][0] != '0') {
+			fprintf(stderr, "Enter a valid PID.\n");
+			fprintf(stderr, "Usage: %s pid [output-file-name]\n", argv[0]);
+			return -1;
+		}
+		if (argc == 2) {
+			snprintf(core_file, 15, "core.%d", pid);
+			ret = do_coredump(pid, core_file);
+		} else
+			ret = do_coredump(pid, argv[2]);
+
+		if (ret == -1)
+			gencore_log("Failed to create core file.\n");
+	}
+
+	return ret;
+}


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 03/33] Process Status
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
  2014-03-20  9:39 ` [PATCH 01/33] Configure and Make files Janani Venkataraman
  2014-03-20  9:39 ` [PATCH 02/33] Validity of arguments Janani Venkataraman
@ 2014-03-20  9:39 ` Janani Venkataraman
  2014-03-20  9:39 ` [PATCH 04/33] Hold threads Janani Venkataraman
                   ` (31 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Fetch the process status from /proc/pid/stat as it will be required for the dump.

Signed-off-by: Suzuki K. Poulose <suzuki@in.ibm.com>
Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/Makefile.am |    2 +
 src/coredump.c  |    4 +++
 src/coredump.h  |   13 ++++++++
 src/proc.c      |   86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 104 insertions(+), 1 deletion(-)
 create mode 100644 src/coredump.h
 create mode 100644 src/proc.c

diff --git a/src/Makefile.am b/src/Makefile.am
index f7b25fa..9e5d3c0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,5 +3,5 @@ HAVE_SYSTEMD_SOCKET_SUPPORT = 0
 CFLAGS += -I. -DHAVE_SYSTEMD_SOCKET_SUPPORT='$(HAVE_SYSTEMD_SOCKET_SUPPORT)'
 
 bin_PROGRAMS = gencore
-gencore_SOURCES = coredump.c
+gencore_SOURCES = coredump.c proc.c
 
diff --git a/src/coredump.c b/src/coredump.c
index 7a7fe11..ad9ee7d 100644
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -26,10 +26,14 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <coredump.h>
 
 /* For logging all the messages */
 FILE *fp_log;
 
+/* Status of the dump */
+int status;
+
 /* Logging messages */
 void gencore_log(char *fmt, ...)
 {
diff --git a/src/coredump.h b/src/coredump.h
new file mode 100644
index 0000000..cc77197
--- /dev/null
+++ b/src/coredump.h
@@ -0,0 +1,13 @@
+#define COMM_LEN 17            /* Maximum length of command line */
+#define NUM_STAT_FEILDS 30     /* Number of fields read from /proc/pid/stat */
+
+/* Status of the dump */
+extern int status;
+
+/* Structure for Status of process */
+struct pid_stat {
+	int ps_pid;
+	char ps_comm[COMM_LEN];
+	char ps_state;
+	unsigned long long ps_num[NUM_STAT_FEILDS];
+};
diff --git a/src/proc.c b/src/proc.c
new file mode 100644
index 0000000..6c9e804
--- /dev/null
+++ b/src/proc.c
@@ -0,0 +1,86 @@
+/*
+ * /proc/ helper routines for gencore
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2013
+ *
+ * Authors:
+ *      Janani Venkataraman <jananve@in.ibm.com>
+ *      Suzuki K. Poulose <suzuki@in.ibm.com>
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <coredump.h>
+
+/* Get Process Stats */
+int get_pid_stat(int pid, struct pid_stat *ps)
+{
+	int ret = -1, i;
+	char junk;
+	char filename[40];
+	FILE *fin;
+
+	snprintf(filename, 40, "/proc/%d/stat", pid);
+	fin = fopen(filename, "r");
+	if (fin == NULL) {
+		status = errno;
+		gencore_log("Failure while fetching thread status from %s.\n",
+								filename);
+		return -1;
+	}
+
+	/* Read pid */
+	fscanf(fin, "%d", &ps->ps_pid);
+
+	/* Skip till '(' */
+	while (fscanf(fin, "%c", &junk) != EOF && junk != '(');
+	if (junk != '(')  {
+		status = errno;
+		gencore_log("Failure while fetching thread status from %s.\n",
+								filename);
+		goto err;
+	}
+
+	/* Read Command Line */
+	fscanf(fin, "%[^)]", ps->ps_comm);
+
+	/* Skip the ')' */
+	while (fscanf(fin, "%c", &junk) != EOF && junk != ')');
+	if (junk != ')')  {
+		status = errno;
+		gencore_log("Failure while fetching thread status from %s.\n",
+								filename);
+		goto err;
+	}
+
+	/* Reading the space */
+	fscanf(fin, "%c", &junk);
+
+	/* State */
+	fscanf(fin, "%c", &ps->ps_state);
+
+	/* Read the rest of the fields */
+	for (i = 0; i < NUM_STAT_FEILDS &&
+			(fscanf(fin, "%lld", &ps->ps_num[i]) != EOF); i++);
+
+	if (i == NUM_STAT_FEILDS)
+		ret = 0;
+
+err:
+	fclose(fin);
+	return ret;
+}


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 04/33] Hold threads
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (2 preceding siblings ...)
  2014-03-20  9:39 ` [PATCH 03/33] Process Status Janani Venkataraman
@ 2014-03-20  9:39 ` Janani Venkataraman
  2014-03-20 19:01   ` Pavel Emelyanov
  2014-03-20  9:39 ` [PATCH 05/33] Fetching Memory maps Janani Venkataraman
                   ` (30 subsequent siblings)
  34 siblings, 1 reply; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Getting number of threads and their respective IDs through /proc/pid/stat and
/proc/pid/task.

The threads are then seized and interrupted. After the dump is taken they are
detached.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.c |  149 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/coredump.h |   10 ++++
 src/proc.c     |   52 ++++++++++++++++++++
 3 files changed, 210 insertions(+), 1 deletion(-)

diff --git a/src/coredump.c b/src/coredump.c
index ad9ee7d..dd9089f 100644
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -26,6 +26,9 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <dirent.h>
+#include <errno.h>
+#include <sys/ptrace.h>
 #include <coredump.h>
 
 /* For logging all the messages */
@@ -43,10 +46,154 @@ void gencore_log(char *fmt, ...)
 	va_end(argptr);
 }
 
+/* Core process object */
+struct core_proc cp;
+
+/* Initialised core process members */
+void init_core(void)
+{
+	memset(&cp, 0, sizeof(struct core_proc));
+}
+
+/* Gets the Thread IDS and siezes them */
+int seize_threads(int pid)
+{
+	char filename[40];
+	DIR *dir;
+	int ct = 0, ret = 0, tmp_tid;
+	struct dirent *entry;
+	char state;
+
+	ret = get_thread_count(pid);
+	if (ret == -1)
+		return -1;
+
+	cp.thread_count = ret;
+	cp.t_id = calloc(cp.thread_count, sizeof(int));
+	if (!cp.t_id) {
+		status = errno;
+		gencore_log("Could not allocate memory for thread_ids.\n");
+		return -1;
+	}
+
+	snprintf(filename, 40, "/proc/%d/task", pid);
+	dir = opendir(filename);
+
+	while ((entry = readdir(dir))) {
+		if (entry->d_type == DT_DIR && entry->d_name[0] != '.') {
+			tmp_tid = atoi(entry->d_name);
+			ret = ptrace(PTRACE_SEIZE, tmp_tid, 0, 0);
+			if (ret) {
+				state = get_thread_status(tmp_tid);
+				if (state == 'Z')
+					goto assign;
+				status = errno;
+				gencore_log("Could not seize thread: %d\n",
+								tmp_tid);
+				break;
+			}
+			ret = ptrace(PTRACE_INTERRUPT, tmp_tid, 0, 0);
+			if (ret) {
+				state = get_thread_status(tmp_tid);
+				if (state == 'Z')
+					goto assign;
+				status = errno;
+				gencore_log("Could not interrupt thread: %d\n",
+								tmp_tid);
+				break;
+			}
+assign:
+			/* If a new thread, is created after we fetch the thread_count,
+			 * we may encounter a buffer overflow situation in the cp_tid.
+			 * Hence we check this case and re-allocate memory if required.
+			 */
+			cp.t_id[ct++] = tmp_tid;
+		}
+	}
+
+	/* Reassigning based on successful seizes */
+	cp.thread_count = ct;
+
+	closedir(dir);
+
+	/* Successful seize and interrupt on all threads makes ret = 0 */
+	return ret;
+}
+
+/* Wait for threads to stop */
+int wait_for_threads_to_stop(void)
+{
+	int i;
+	char state;
+
+	/*
+	 * We check for the process to stop infinitely now. We need
+	 * to break out after some definite time. Need to work on
+	 * that.
+	 */
+	for (i = 0; i < cp.thread_count; i++) {
+		do {
+			state = get_thread_status(cp.t_id[i]);
+			if (state != 't')
+				sched_yield();
+		} while (state != 't' && state!='Z' && state != -1);
+		if (state == -1)
+			return -1;
+	}
+
+	return 0;
+}
+
+/* Release the threads that are held */
+int release_threads(void)
+{
+	int i, ret = 0;
+	char state;
+
+	/* Detach the process to be dumped */
+	for (i = 0; i < cp.thread_count; i++) {
+		state = get_thread_status(cp.t_id[i]);
+		if (state == 't') {
+			ret += ptrace(PTRACE_DETACH, cp.t_id[i], 0, 0);
+			if (ret)
+				gencore_log("Could not detach from thread: %d\n",
+								cp.t_id[i]);
+		}
+	}
+
+	/* Successful detach on all threads makes ret = 0 */
+	return ret;
+}
+
 /* Performs the core dump */
 int do_coredump(int pid, char *core_file)
 {
-	return 0;
+	int ret;
+
+	/* Initialise members of core process */
+	init_core();
+
+	/* Getting thread information and seizing them */
+	ret = seize_threads(pid);
+	if (ret)
+		goto cleanup;
+
+	/* Wait for threads to stop */
+	ret = wait_for_threads_to_stop();
+	if (ret)
+		goto cleanup;
+
+cleanup:
+
+	/* Release the threads */
+	release_threads();
+
+	if (cp.t_id)
+		free(cp.t_id);
+
+	errno = status;
+
+	return ret;
 }
 
 /* Daemon for self dump */
diff --git a/src/coredump.h b/src/coredump.h
index cc77197..00cb008 100644
--- a/src/coredump.h
+++ b/src/coredump.h
@@ -1,6 +1,10 @@
 #define COMM_LEN 17            /* Maximum length of command line */
 #define NUM_STAT_FEILDS 30     /* Number of fields read from /proc/pid/stat */
 
+#define THREAD_COUNT_IDX 16	/* Index for number of threads */
+
+#define __ps_thread_count ps_num[THREAD_COUNT_IDX]	/* Process Information */
+
 /* Status of the dump */
 extern int status;
 
@@ -11,3 +15,9 @@ struct pid_stat {
 	char ps_state;
 	unsigned long long ps_num[NUM_STAT_FEILDS];
 };
+
+/* Structure for the Core of the Process */
+struct core_proc {
+	int thread_count;		/* Number of threads */
+	int *t_id;			/* Threads_ids of all the threads */
+};
diff --git a/src/proc.c b/src/proc.c
index 6c9e804..fc16d90 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -24,6 +24,7 @@
 
 #include <stdio.h>
 #include <errno.h>
+#include <stdlib.h>
 #include <coredump.h>
 
 /* Get Process Stats */
@@ -84,3 +85,54 @@ err:
 	fclose(fin);
 	return ret;
 }
+
+/* Counts the number of threads in the process */
+int get_thread_count(int pid)
+{
+	struct pid_stat p;
+	int ret;
+
+	ret = get_pid_stat(pid, &p);
+	if (ret)
+		return -1;
+
+	return p.__ps_thread_count;
+}
+
+/* Fetched thread status */
+char get_thread_status(int tid)
+{
+	int ret;
+	char filename[40], buff[40];
+	FILE *fin;
+	char *pos;
+
+	snprintf(filename, 40, "/proc/%d/stat", tid);
+	fin = fopen(filename, "r");
+	if (fin == NULL) {
+		status = errno;
+		gencore_log("Failure while fetching thread state from %s.\n",
+								filename);
+		return -1;
+	}
+
+	ret = fread(buff, 40, 1, fin);
+	if (ret == 0) {
+		status = errno;
+		gencore_log("Failure while fetching thread state from %s.\n",
+								filename);
+		return -1;
+	}
+
+	pos = strrchr(buff, ')');
+	if (pos == NULL) {
+		status = errno;
+		gencore_log("Failure while fetching thread state from %s.\n",
+								filename);
+		return -1;
+	}
+
+	fclose(fin);
+
+	return buff[pos - buff + 2];
+}


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 05/33] Fetching Memory maps
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (3 preceding siblings ...)
  2014-03-20  9:39 ` [PATCH 04/33] Hold threads Janani Venkataraman
@ 2014-03-20  9:39 ` Janani Venkataraman
  2014-03-20  9:39 ` [PATCH 06/33] Check ELF class Janani Venkataraman
                   ` (29 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Fetching virtual memory areas through /proc/pid/maps and storing it in a
linked list in order to populate the program headers and file maps.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.c |    8 +++++
 src/coredump.h |   11 ++++++
 src/proc.c     |   95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 114 insertions(+)

diff --git a/src/coredump.c b/src/coredump.c
index dd9089f..7a559e2 100644
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -183,6 +183,11 @@ int do_coredump(int pid, char *core_file)
 	if (ret)
 		goto cleanup;
 
+	/* Get VMAS */
+	ret = get_vmas(pid, &cp);
+	if (ret)
+		goto cleanup;
+
 cleanup:
 
 	/* Release the threads */
@@ -191,6 +196,9 @@ cleanup:
 	if (cp.t_id)
 		free(cp.t_id);
 
+	if (cp.vmas)
+		free_maps(cp.vmas);
+
 	errno = status;
 
 	return ret;
diff --git a/src/coredump.h b/src/coredump.h
index 00cb008..291e13b 100644
--- a/src/coredump.h
+++ b/src/coredump.h
@@ -16,8 +16,19 @@ struct pid_stat {
 	unsigned long long ps_num[NUM_STAT_FEILDS];
 };
 
+/* Structure for maps */
+struct maps {
+	unsigned long long src, dst, offset;
+	char r, w, x;
+	long inode;
+	struct maps *next;
+	char fname[0];
+};
+
 /* Structure for the Core of the Process */
 struct core_proc {
 	int thread_count;		/* Number of threads */
 	int *t_id;			/* Threads_ids of all the threads */
+	struct maps *vmas;		/* VMAs */
+	int phdrs_count;		/* Number of Program headers */
 };
diff --git a/src/proc.c b/src/proc.c
index fc16d90..a401aa5 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include <errno.h>
 #include <stdlib.h>
+#include <string.h>
 #include <coredump.h>
 
 /* Get Process Stats */
@@ -136,3 +137,97 @@ char get_thread_status(int tid)
 
 	return buff[pos - buff + 2];
 }
+
+/* Free Maps */
+void free_maps(struct maps *head)
+{
+	struct maps *tmp;
+
+	while (head) {
+		tmp = head->next;
+		free(head);
+		head = tmp;
+	}
+}
+
+/* Append a new VMA */
+void append_maps(struct maps *new_map, struct core_proc *cp)
+{
+	struct maps *tmp;
+
+	if (cp->vmas == NULL)
+		cp->vmas = new_map;
+	else {
+		tmp = cp->vmas;
+		while (tmp->next != NULL)
+			tmp = tmp->next;
+		tmp->next = new_map;
+	}
+}
+
+/* Collects virtual memory areas */
+int get_vmas(int pid, struct core_proc *cp)
+{
+	char filename[40];
+	char buff[4096];
+	char src[128];
+	char dst[128];
+	char fname[4096];
+	char page_offset[128];
+	char inode[128];
+	char r, w, x;
+	char junk[30];
+	FILE *fin;
+	struct maps *tmp;
+	long tmp_inode;
+
+	snprintf(filename, 40, "/proc/%d/maps", pid);
+	fin = fopen(filename, "r");
+	if (fin == NULL) {
+		status = errno;
+		gencore_log("Failure in fetching Memory Mappings %s.\n",
+								filename);
+		return -1;
+	}
+
+	while (fgets(buff, 4096, fin)) {
+
+		sscanf(buff, "%[^-]%c%s %c%c%c%c %s %s %s %s", src, &junk[0],
+					dst, &r, &w, &x, &junk[0],
+					page_offset, junk, inode, fname);
+
+		tmp_inode = strtol(inode, NULL, 16);
+
+		if (tmp_inode)
+			tmp = malloc(sizeof(struct maps) + strlen(fname) + 1);
+		else
+			tmp = malloc(sizeof(struct maps));
+		if (!tmp) {
+			status = errno;
+			gencore_log("Failure in allocating memory for memory maps.\n");
+			fclose(fin);
+			return -1;
+		}
+
+		tmp->src = strtoull(src, NULL, 16);
+		tmp->dst = strtoull(dst, NULL, 16);
+		tmp->offset = strtoull(page_offset, NULL, 16);
+		tmp->r = r;
+		tmp->w = w;
+		tmp->x = x;
+		tmp->inode = tmp_inode;
+
+		if (tmp->inode != 0)
+			strcpy(tmp->fname, fname);
+
+		tmp->next = NULL;
+		append_maps(tmp, cp);
+		cp->phdrs_count++;
+	}
+
+	/* One extra for the PT_NOTE */
+	cp->phdrs_count++;
+
+	fclose(fin);
+	return 0;
+}


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 06/33] Check ELF class
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (4 preceding siblings ...)
  2014-03-20  9:39 ` [PATCH 05/33] Fetching Memory maps Janani Venkataraman
@ 2014-03-20  9:39 ` Janani Venkataraman
  2014-03-20  9:39 ` [PATCH 07/33] Do elf_coredump Janani Venkataraman
                   ` (28 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

The process to be dumped can be either a 32bit application or a 64 bit
application. We first need to check this and proceed with the dump accordingly.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.c |    5 +++++
 src/coredump.h |    1 +
 src/proc.c     |   45 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 51 insertions(+)

diff --git a/src/coredump.c b/src/coredump.c
index 7a559e2..f9c7176 100644
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -188,6 +188,11 @@ int do_coredump(int pid, char *core_file)
 	if (ret)
 		goto cleanup;
 
+	/* Compat Support */
+	cp.elf_class = ret = get_elf_class(pid, &cp);
+	if (ret == -1)
+		goto cleanup;
+
 cleanup:
 
 	/* Release the threads */
diff --git a/src/coredump.h b/src/coredump.h
index 291e13b..25042f5 100644
--- a/src/coredump.h
+++ b/src/coredump.h
@@ -31,4 +31,5 @@ struct core_proc {
 	int *t_id;			/* Threads_ids of all the threads */
 	struct maps *vmas;		/* VMAs */
 	int phdrs_count;		/* Number of Program headers */
+	int elf_class;			/* Elf class of the process */
 };
diff --git a/src/proc.c b/src/proc.c
index a401aa5..3a4a387 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <coredump.h>
+#include <elf.h>
 
 /* Get Process Stats */
 int get_pid_stat(int pid, struct pid_stat *ps)
@@ -231,3 +232,47 @@ int get_vmas(int pid, struct core_proc *cp)
 	fclose(fin);
 	return 0;
 }
+
+/* Check if its ELF */
+int check_elf_hdr(unsigned char *elf_ident)
+{
+	if (memcmp(elf_ident, ELFMAG, SELFMAG) != 0)
+		return -1;
+
+	return 0;
+}
+
+/* Get ELF Class */
+int get_elf_class(int pid, struct core_proc *cp)
+{
+	FILE *fin;
+	unsigned char elf_magic[EI_NIDENT];
+	char filename[40];
+	int ret;
+
+	snprintf(filename, 40, "/proc/%d/exe", pid);
+	fin = fopen(filename, "r");
+	if (fin == NULL) {
+		status = errno;
+		gencore_log("Failure while fetching the ELF header of the executable from %s.\n", filename);
+		return -1;
+	}
+
+	ret = fread(elf_magic, EI_NIDENT, 1, fin);
+	if (ret != 1) {
+		status = errno;
+		gencore_log("Failure while fetching the ELF header of the executable from %s.\n", filename);
+		fclose(fin);
+		return -1;
+	}
+
+	if (check_elf_hdr(elf_magic)) {
+		status = EINVAL;
+		gencore_log("Process to be dumped is not an ELF.\n");
+		return -1;
+	}
+
+	fclose(fin);
+
+	return elf_magic[EI_CLASS];
+}


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 07/33] Do elf_coredump
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (5 preceding siblings ...)
  2014-03-20  9:39 ` [PATCH 06/33] Check ELF class Janani Venkataraman
@ 2014-03-20  9:39 ` Janani Venkataraman
  2014-03-20  9:40 ` [PATCH 08/33] Fills elf header Janani Venkataraman
                   ` (27 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Perform the actual dump depending on whether it is 32 bit or 64 bit.

We create three files elf.c elf32.c and elf64.c. In elf.c we have all the elf
related code in a generic format(not 32 or 64 bit specific). In elf32.c and
elf64.c we include elf.c and #define the required datatypes and functions into
32 or 64 specific values respectively.

Essentially we have two copies of elf.c, one which is 32 bit specific and the
other 64 bit specific and hence the appropriate function is called based on the
application to be dumped.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/Makefile.am |    2 +-
 src/coredump.c  |    9 +++++++++
 src/elf.c       |   31 +++++++++++++++++++++++++++++++
 src/elf32.c     |   33 +++++++++++++++++++++++++++++++++
 src/elf64.c     |   33 +++++++++++++++++++++++++++++++++
 5 files changed, 107 insertions(+), 1 deletion(-)
 create mode 100644 src/elf.c
 create mode 100644 src/elf32.c
 create mode 100644 src/elf64.c

diff --git a/src/Makefile.am b/src/Makefile.am
index 9e5d3c0..90d8b25 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,5 +3,5 @@ HAVE_SYSTEMD_SOCKET_SUPPORT = 0
 CFLAGS += -I. -DHAVE_SYSTEMD_SOCKET_SUPPORT='$(HAVE_SYSTEMD_SOCKET_SUPPORT)'
 
 bin_PROGRAMS = gencore
-gencore_SOURCES = coredump.c proc.c
+gencore_SOURCES = coredump.c proc.c elf32.c elf64.c
 
diff --git a/src/coredump.c b/src/coredump.c
index f9c7176..b1ee99d 100644
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -28,6 +28,7 @@
 #include <stdlib.h>
 #include <dirent.h>
 #include <errno.h>
+#include <elf.h>
 #include <sys/ptrace.h>
 #include <coredump.h>
 
@@ -193,6 +194,14 @@ int do_coredump(int pid, char *core_file)
 	if (ret == -1)
 		goto cleanup;
 
+	/* Do elf_dump */
+	if (cp.elf_class == ELFCLASS32)
+		ret = do_elf32_coredump(pid, &cp);
+	else
+		ret = do_elf64_coredump(pid, &cp);
+	if (ret)
+		goto cleanup;
+
 cleanup:
 
 	/* Release the threads */
diff --git a/src/elf.c b/src/elf.c
new file mode 100644
index 0000000..280df13
--- /dev/null
+++ b/src/elf.c
@@ -0,0 +1,31 @@
+/*
+ * ELF helper routines for gencore
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2013
+ *
+ * Authors:
+ *      Janani Venkataraman <jananve@in.ibm.com>
+ *      Suzuki K. Poulose <suzuki@in.ibm.com>
+ */
+
+#include <stdio.h>
+#include "coredump.h"
+
+int do_elf_coredump(int pid, struct core_proc *cp)
+{
+	return 0;
+}
diff --git a/src/elf32.c b/src/elf32.c
new file mode 100644
index 0000000..d6b40b4
--- /dev/null
+++ b/src/elf32.c
@@ -0,0 +1,33 @@
+/*
+ * ELF helper routines for gencore
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2013
+ *
+ * Authors:
+ *      Janani Venkataraman <jananve@in.ibm.com>
+ */
+
+/*
+ * We include elf.c to add all the elf specific operations here.
+ * In this file, we define all 32 bit specific data and hence
+ * this file would contain all elf 32 bit specific functions
+ * and operations once elf.c is included.
+ */
+
+#define do_elf_coredump do_elf32_coredump
+
+#include "elf.c"
diff --git a/src/elf64.c b/src/elf64.c
new file mode 100644
index 0000000..d8b5e89
--- /dev/null
+++ b/src/elf64.c
@@ -0,0 +1,33 @@
+/*
+ * ELF helper routines for gencore
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2013
+ *
+ * Authors:
+ *      Janani Venkataraman <jananve@in.ibm.com>
+ */
+
+/*
+ * We include elf.c to add all the elf specific operations here.
+ * In this file, we define all 64 bit specific data and hence
+ * this file would contain all elf 64 bit specific functions
+ * and operations once elf.c is included.
+ */
+
+#define do_elf_coredump do_elf64_coredump
+
+#include "elf.c"


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 08/33] Fills elf header
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (6 preceding siblings ...)
  2014-03-20  9:39 ` [PATCH 07/33] Do elf_coredump Janani Venkataraman
@ 2014-03-20  9:40 ` Janani Venkataraman
  2014-03-20  9:40 ` [PATCH 09/33] Adding notes infrastructure Janani Venkataraman
                   ` (26 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:40 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Populates the ELF header. It fills the magic number, version, machine number of
program headers and other members of the ELF_HEADER.

All the information is derived from the ELF_HEADER of the exe of the process to
be dumped through /proc/pid/exe.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.c |    3 ++
 src/coredump.h |    1 +
 src/elf.c      |   96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/elf32.c    |    4 ++
 src/elf64.c    |    4 ++
 5 files changed, 108 insertions(+)

diff --git a/src/coredump.c b/src/coredump.c
index b1ee99d..de0a7ce 100644
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -213,6 +213,9 @@ cleanup:
 	if (cp.vmas)
 		free_maps(cp.vmas);
 
+	if (cp.elf_hdr)
+		free(cp.elf_hdr);
+
 	errno = status;
 
 	return ret;
diff --git a/src/coredump.h b/src/coredump.h
index 25042f5..4e508c1 100644
--- a/src/coredump.h
+++ b/src/coredump.h
@@ -32,4 +32,5 @@ struct core_proc {
 	struct maps *vmas;		/* VMAs */
 	int phdrs_count;		/* Number of Program headers */
 	int elf_class;			/* Elf class of the process */
+	void *elf_hdr;			/* Stores the ELF_header */
 };
diff --git a/src/elf.c b/src/elf.c
index 280df13..9f65c77 100644
--- a/src/elf.c
+++ b/src/elf.c
@@ -22,10 +22,106 @@
  *      Suzuki K. Poulose <suzuki@in.ibm.com>
  */
 
+#include <errno.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/uio.h>
+#include <linux/elf.h>
 #include "coredump.h"
 
+/* Fetchs ELF header of the executable */
+static int get_elf_hdr_exe_file(int pid, Elf_Ehdr *elf)
+{
+	char filename[40];
+	int ret;
+	FILE *fin;
+
+	snprintf(filename, 40, "/proc/%d/exe", pid);
+	fin = fopen(filename, "r");
+	if (fin == NULL) {
+		status = errno;
+		gencore_log("Failed to open %s for checking the ELF header.",
+								filename);
+		return -1;
+	}
+
+	ret = fread(elf, sizeof(*elf), 1, fin);
+	if (ret != 1) {
+		status = errno;
+		gencore_log("Failure while fetching the ELF header of the executable from %s.\n", filename);
+		fclose(fin);
+		return -1;
+	}
+
+	fclose(fin);
+
+	return 0;
+}
+
+/* Fills the ELF HEADER */
+static int fill_elf_header(int pid, struct core_proc *cp)
+{
+	Elf_Ehdr elf, *cp_elf;
+	int ret;
+
+	cp->elf_hdr = malloc(sizeof(Elf_Ehdr));
+	if (!cp->elf_hdr) {
+		status = errno;
+		gencore_log("Failure in allocating memory for ELF header.\n");
+		return -1;
+	}
+
+	cp_elf = (Elf_Ehdr *)cp->elf_hdr;
+
+	memset(cp_elf, 0, EI_NIDENT);
+
+	ret = get_elf_hdr_exe_file(pid, &elf);
+	if (ret == -1)
+		return -1;
+
+	/* Magic Number */
+	memcpy(cp_elf->e_ident, ELFMAG, SELFMAG);
+
+	cp_elf->e_ident[EI_CLASS] = elf.e_ident[EI_CLASS];
+	cp_elf->e_ident[EI_DATA] = elf.e_ident[EI_DATA];
+	cp_elf->e_ident[EI_VERSION] = EV_CURRENT;
+	cp_elf->e_ident[EI_OSABI] = EI_OSABI;
+
+	/* Rest of the fields */
+	cp_elf->e_entry = 0;
+	cp_elf->e_type = ET_CORE;
+	cp_elf->e_machine = elf.e_machine;
+	cp_elf->e_version = EV_CURRENT;
+	cp_elf->e_phoff = sizeof(Elf_Ehdr);
+	cp_elf->e_shoff = 0;
+	cp_elf->e_flags = 0;
+	cp_elf->e_ehsize =  sizeof(Elf_Ehdr);
+	cp_elf->e_phentsize = sizeof(Elf_Phdr);
+
+	if (cp->phdrs_count > PN_XNUM) {
+		cp_elf->e_phnum = PN_XNUM;
+		cp_elf->e_shentsize = sizeof(Elf_Shdr);
+		cp_elf->e_shnum = 1;
+	} else {
+		cp_elf->e_phnum = cp->phdrs_count;
+		cp_elf->e_shentsize = 0;
+		cp_elf->e_shnum = 0;
+	}
+
+	cp_elf->e_shstrndx = SHN_UNDEF;
+
+	return 0;
+}
+
 int do_elf_coredump(int pid, struct core_proc *cp)
 {
+	int ret;
+
+	/* Fill ELF Header */
+	ret = fill_elf_header(pid, cp);
+	if (ret)
+		return -1;
+
 	return 0;
 }
diff --git a/src/elf32.c b/src/elf32.c
index d6b40b4..1a95ff2 100644
--- a/src/elf32.c
+++ b/src/elf32.c
@@ -30,4 +30,8 @@
 
 #define do_elf_coredump do_elf32_coredump
 
+#define Elf_Ehdr Elf32_Ehdr
+#define Elf_Phdr Elf32_Phdr
+#define Elf_Shdr Elf32_Shdr
+
 #include "elf.c"
diff --git a/src/elf64.c b/src/elf64.c
index d8b5e89..953b826 100644
--- a/src/elf64.c
+++ b/src/elf64.c
@@ -30,4 +30,8 @@
 
 #define do_elf_coredump do_elf64_coredump
 
+#define Elf_Ehdr Elf64_Ehdr
+#define Elf_Phdr Elf64_Phdr
+#define Elf_Shdr Elf64_Shdr
+
 #include "elf.c"


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 09/33] Adding notes infrastructure
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (7 preceding siblings ...)
  2014-03-20  9:40 ` [PATCH 08/33] Fills elf header Janani Venkataraman
@ 2014-03-20  9:40 ` Janani Venkataraman
  2014-03-20  9:40 ` [PATCH 10/33] Populates PRPS info Janani Venkataraman
                   ` (25 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:40 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Creating Elf_note structure and adding the required functions to add the notes.

Signed-off-by: Suzuki K. Poulose <suzuki@in.ibm.com>
Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.c |   15 ++++++++++++
 src/coredump.h |   13 ++++++++++
 src/elf.c      |   73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/elf32.c    |    1 +
 src/elf64.c    |    1 +
 5 files changed, 103 insertions(+)

diff --git a/src/coredump.c b/src/coredump.c
index de0a7ce..0fd6343e 100644
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -166,6 +166,18 @@ int release_threads(void)
 	return ret;
 }
 
+/* Free Notes */
+void free_notes(struct mem_note *head)
+{
+	struct mem_note *tmp;
+
+	while (head) {
+		tmp = head->next;
+		free(head);
+		head = tmp;
+	}
+}
+
 /* Performs the core dump */
 int do_coredump(int pid, char *core_file)
 {
@@ -216,6 +228,9 @@ cleanup:
 	if (cp.elf_hdr)
 		free(cp.elf_hdr);
 
+	if (cp.notes)
+		free_notes(cp.notes);
+
 	errno = status;
 
 	return ret;
diff --git a/src/coredump.h b/src/coredump.h
index 4e508c1..9b19f19 100644
--- a/src/coredump.h
+++ b/src/coredump.h
@@ -25,6 +25,18 @@ struct maps {
 	char fname[0];
 };
 
+/*
+ * Structure for Notes
+ * We follow this linked list data-type as we dont know the number of notes
+ * as that depends on the architecture. Also the notebuf contains the final
+ * in-file format for the note data.
+ */
+struct mem_note {
+	unsigned char *notebuf;		/* Notes - type, name_sz, datasz, name and data */
+	unsigned int size;		/* Size of Note */
+	struct mem_note *next;
+};
+
 /* Structure for the Core of the Process */
 struct core_proc {
 	int thread_count;		/* Number of threads */
@@ -33,4 +45,5 @@ struct core_proc {
 	int phdrs_count;		/* Number of Program headers */
 	int elf_class;			/* Elf class of the process */
 	void *elf_hdr;			/* Stores the ELF_header */
+	struct mem_note *notes;		/* Head of Notes */
 };
diff --git a/src/elf.c b/src/elf.c
index 9f65c77..dfcb1d7 100644
--- a/src/elf.c
+++ b/src/elf.c
@@ -30,6 +30,79 @@
 #include <linux/elf.h>
 #include "coredump.h"
 
+#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
+
+/* Appending the note to the list */
+static void append_note(struct mem_note *new_note, struct core_proc *cp)
+{
+	struct mem_note *tmp;
+
+	if (cp->notes == NULL)
+		cp->notes = new_note;
+	else {
+		tmp = cp->notes;
+		while (tmp->next != NULL)
+			tmp = tmp->next;
+		tmp->next = new_note;
+	}
+}
+
+/* Adding a new note */
+static int add_note(const char *name, int type, unsigned int data_sz, void *data,
+						struct core_proc *cp)
+{
+	unsigned char *ptr, *notebuf;
+	unsigned int namelen, size, data_offset;
+	Elf_Nhdr *note;
+	struct mem_note *tmp = malloc(sizeof(struct mem_note));
+	if (!tmp) {
+		status = errno;
+		gencore_log("Failure in adding note.\n");
+		return -1;
+	}
+
+	/* Calculate the size of the Notes */
+	namelen = strlen(name) + 1;
+	size = sizeof(Elf_Nhdr);
+	size += namelen;
+
+	/* Note down the offset where data is to be stored */
+	data_offset = size = roundup(size, 4);
+	size += data_sz;
+	size = roundup(size, 4);
+
+	/* Allocate the required size, initialized to 0 */
+	notebuf = calloc(1, size);
+	if (!notebuf) {
+		status = errno;
+		gencore_log("Could not allocate memory for Notes buffer.\n");
+		return -1;
+	}
+
+	note = (Elf_Nhdr *)notebuf;
+
+	/* Where name should be stored */
+	ptr = (unsigned char *) (note + 1);
+
+	note->n_type = type;
+	note->n_namesz = strlen(name) + 1;
+	note->n_descsz = data_sz;
+
+	/* Store name */
+	memcpy(ptr, name, namelen);
+
+	/* Store data */
+	memcpy(notebuf + data_offset, data, data_sz);
+
+	tmp->notebuf = notebuf;
+	tmp->size = size;
+	tmp->next = NULL;
+
+	append_note(tmp, cp);
+
+	return 0;
+}
+
 /* Fetchs ELF header of the executable */
 static int get_elf_hdr_exe_file(int pid, Elf_Ehdr *elf)
 {
diff --git a/src/elf32.c b/src/elf32.c
index 1a95ff2..01b3923 100644
--- a/src/elf32.c
+++ b/src/elf32.c
@@ -33,5 +33,6 @@
 #define Elf_Ehdr Elf32_Ehdr
 #define Elf_Phdr Elf32_Phdr
 #define Elf_Shdr Elf32_Shdr
+#define Elf_Nhdr Elf32_Nhdr
 
 #include "elf.c"
diff --git a/src/elf64.c b/src/elf64.c
index 953b826..a99a73b 100644
--- a/src/elf64.c
+++ b/src/elf64.c
@@ -33,5 +33,6 @@
 #define Elf_Ehdr Elf64_Ehdr
 #define Elf_Phdr Elf64_Phdr
 #define Elf_Shdr Elf64_Shdr
+#define Elf_Nhdr Elf64_Nhdr
 
 #include "elf.c"


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 10/33] Populates PRPS info
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (8 preceding siblings ...)
  2014-03-20  9:40 ` [PATCH 09/33] Adding notes infrastructure Janani Venkataraman
@ 2014-03-20  9:40 ` Janani Venkataraman
  2014-03-20  9:40 ` [PATCH 11/33] Populate AUXV Janani Venkataraman
                   ` (24 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:40 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Populates the prps_info by reading /proc/pid/stat and /proc/pid/cmdline.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.h   |   10 +++++++++
 src/elf-compat.h |   48 +++++++++++++++++++++++++++++++++++++++++++++
 src/elf.c        |   58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/elf32.c      |    1 +
 src/elf64.c      |    1 +
 5 files changed, 118 insertions(+)
 create mode 100644 src/elf-compat.h

diff --git a/src/coredump.h b/src/coredump.h
index 9b19f19..d5562fe 100644
--- a/src/coredump.h
+++ b/src/coredump.h
@@ -1,9 +1,19 @@
 #define COMM_LEN 17            /* Maximum length of command line */
 #define NUM_STAT_FEILDS 30     /* Number of fields read from /proc/pid/stat */
 
+#define PPID 0			/* Index for parent process ID */
+#define PGRP 1			/* Index for process group ID */
+#define SID 2			/* Index for session ID */
+#define FLAG 5			/* Index for flags */
+#define NICE 15		/* Index for nice value */
 #define THREAD_COUNT_IDX 16	/* Index for number of threads */
 
 #define __ps_thread_count ps_num[THREAD_COUNT_IDX]	/* Process Information */
+#define __ps_ppid ps_num[PPID]				/* Process PID */	
+#define __ps_pgrp ps_num[PGRP]				/* Process Group ID */ 
+#define __ps_sid ps_num[SID]				/* Process Session ID */
+#define __ps_flag ps_num[FLAG]				/* Process Flags */
+#define __ps_nice ps_num[NICE]				/* Process Nice Value */
 
 /* Status of the dump */
 extern int status;
diff --git a/src/elf-compat.h b/src/elf-compat.h
new file mode 100644
index 0000000..463070a
--- /dev/null
+++ b/src/elf-compat.h
@@ -0,0 +1,48 @@
+/*
+ * ELF structures for gencore
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2013
+ *
+ * Authors:
+ *      Janani Venkataraman <jananve@in.ibm.com>
+ */
+
+#if defined(__PPC64__) || defined(__PPC__)
+typedef unsigned int compat_id;
+#endif
+
+#if defined(__s390x__) || defined(__s390__)
+typedef unsigned short compat_id;
+#endif
+
+#if defined(__x86_64) || defined(__i386)
+typedef unsigned short compat_id;
+#endif
+
+/* Compat structure for PRPS_INFO */
+struct compat_elf_prpsinfo {
+	char				pr_state;
+	char				pr_sname;
+	char				pr_zomb;
+	char				pr_nice;
+	unsigned int			pr_flag;
+	compat_id			pr_uid;
+	compat_id			pr_gid;
+	int				pr_pid, pr_ppid, pr_pgrp, pr_sid;
+	char				pr_fname[16];
+	char				pr_psargs[ELF_PRARGSZ];
+};
diff --git a/src/elf.c b/src/elf.c
index dfcb1d7..18bbeeb 100644
--- a/src/elf.c
+++ b/src/elf.c
@@ -27,7 +27,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/uio.h>
+#include <sys/procfs.h>
 #include <linux/elf.h>
+#include "elf-compat.h"
 #include "coredump.h"
 
 #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
@@ -187,6 +189,57 @@ static int fill_elf_header(int pid, struct core_proc *cp)
 	return 0;
 }
 
+/* Populates PRPS_INFO */
+static int get_prpsinfo(int pid, struct core_proc *cp)
+{
+	char filename[40];
+	int ret;
+	FILE *fin;
+	struct Elf_prpsinfo prps;
+	struct pid_stat p;
+
+	ret = get_pid_stat(pid, &p);
+	if (ret)
+		return -1;
+
+	prps.pr_pid = p.ps_pid;
+	strcpy(prps.pr_fname, p.ps_comm);
+	prps.pr_state = p.ps_state;
+	prps.pr_ppid = p.__ps_ppid;
+	prps.pr_pgrp = p.__ps_pgrp;
+	prps.pr_sid = p.__ps_sid;
+	prps.pr_flag = p.__ps_flag;
+	prps.pr_nice = p.__ps_nice;
+
+	prps.pr_sname = prps.pr_state;
+	if (prps.pr_sname == 'z')
+		prps.pr_zomb = 1;
+	else
+		prps.pr_zomb = 0;
+
+	snprintf(filename, 40, "/proc/%d/cmdline", pid);
+	fin = fopen(filename, "r");
+	if (fin == NULL) {
+		status = errno;
+		gencore_log("Failure while fetching command line arguments from %s.\n", filename);
+		return -1;
+	}
+
+	/* Getting CMDLINE arguments */
+	ret = fread(prps.pr_psargs, ELF_PRARGSZ, 1, fin);
+	if (ret == -1) {
+		status = errno;
+		gencore_log("Failure while fetching command line arguments from %s.\n", filename);
+		fclose(fin);
+		return -1;
+	}
+
+	fclose(fin);
+
+	/* Adding PRPSINFO */
+	return add_note("CORE", NT_PRPSINFO, sizeof(prps), &prps, cp);
+}
+
 int do_elf_coredump(int pid, struct core_proc *cp)
 {
 	int ret;
@@ -196,5 +249,10 @@ int do_elf_coredump(int pid, struct core_proc *cp)
 	if (ret)
 		return -1;
 
+	/* Get prps_info */
+	ret = get_prpsinfo(pid, cp);
+	if (ret)
+		return -1;
+
 	return 0;
 }
diff --git a/src/elf32.c b/src/elf32.c
index 01b3923..8778bed 100644
--- a/src/elf32.c
+++ b/src/elf32.c
@@ -34,5 +34,6 @@
 #define Elf_Phdr Elf32_Phdr
 #define Elf_Shdr Elf32_Shdr
 #define Elf_Nhdr Elf32_Nhdr
+#define Elf_prpsinfo compat_elf_prpsinfo
 
 #include "elf.c"
diff --git a/src/elf64.c b/src/elf64.c
index a99a73b..d062888 100644
--- a/src/elf64.c
+++ b/src/elf64.c
@@ -34,5 +34,6 @@
 #define Elf_Phdr Elf64_Phdr
 #define Elf_Shdr Elf64_Shdr
 #define Elf_Nhdr Elf64_Nhdr
+#define Elf_prpsinfo elf_prpsinfo
 
 #include "elf.c"


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 11/33] Populate AUXV
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (9 preceding siblings ...)
  2014-03-20  9:40 ` [PATCH 10/33] Populates PRPS info Janani Venkataraman
@ 2014-03-20  9:40 ` Janani Venkataraman
  2014-03-20  9:40 ` [PATCH 12/33] Fetch File maps Janani Venkataraman
                   ` (23 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:40 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Populate the auxillary vector using /proc/pid/auxv.

Signed-off-by: Suzuki K. Poulose <suzuki@in.ibm.com>
Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/elf.c |   73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)

diff --git a/src/elf.c b/src/elf.c
index 18bbeeb..b7fd6d0 100644
--- a/src/elf.c
+++ b/src/elf.c
@@ -26,12 +26,16 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
 #include <sys/uio.h>
 #include <sys/procfs.h>
 #include <linux/elf.h>
 #include "elf-compat.h"
 #include "coredump.h"
 
+#define PAGESIZE getpagesize()
+
 #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
 
 /* Appending the note to the list */
@@ -240,6 +244,70 @@ static int get_prpsinfo(int pid, struct core_proc *cp)
 	return add_note("CORE", NT_PRPSINFO, sizeof(prps), &prps, cp);
 }
 
+/* Populate auxillary vector */
+static int get_auxv(int pid, struct core_proc *cp)
+{
+	unsigned char buff[PAGESIZE];
+	char filename[40];
+	int ret, fd, pages;
+	unsigned char *ptr, *auxv;
+	unsigned int auxv_size;
+
+	snprintf(filename, 40, "/proc/%d/auxv", pid);
+
+	fd = open(filename, O_RDONLY);
+	if (fd < 0) {
+		status = errno;
+		gencore_log("Failure while fetching auxv data from %s.\n",
+								filename);
+		return -1;
+	}
+
+	auxv = malloc(PAGESIZE);
+	if (!auxv) {
+		status = errno;
+		gencore_log("Could not allocate memory for the auxv_buffer.\n");
+		close(fd);
+		return -1;
+	}
+	/* Position to copy the auxv data */
+	ptr = auxv;
+	pages = 1;
+	/*
+	 * We read the auxv data page by page and also we don't not
+	 * know the size of auxv, hence we read till ret becomes
+	 * lesser than PAGESIZE.
+	 */
+	while ((ret = read(fd, buff, PAGESIZE)) > 0) {
+		memcpy(ptr, buff, ret);
+		if (ret < PAGESIZE)   /* Finished reading */
+			break;
+		else {
+			/* We have more data to read */
+			pages++;
+			auxv = realloc(auxv, pages * PAGESIZE);
+			ptr = auxv + ((pages - 1) * PAGESIZE);
+		}
+	}
+	if (ret >= 0)
+		auxv_size = ((pages - 1) * PAGESIZE) + ret;
+	else {
+		status = errno;
+		gencore_log("Failure while fetching auxv data from %s.\n", filename);
+		close(fd);
+		free(auxv);
+		return -1;
+	}
+
+	/* Adding AUXV */
+	ret = add_note("CORE", NT_AUXV, auxv_size, auxv, cp);
+
+	close(fd);
+	free(auxv);
+
+	return ret;
+}
+
 int do_elf_coredump(int pid, struct core_proc *cp)
 {
 	int ret;
@@ -254,5 +322,10 @@ int do_elf_coredump(int pid, struct core_proc *cp)
 	if (ret)
 		return -1;
 
+	/* Get Auxillary Vector */
+	ret = get_auxv(pid, cp);
+	if (ret)
+		return -1;
+
 	return 0;
 }


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 12/33] Fetch File maps
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (10 preceding siblings ...)
  2014-03-20  9:40 ` [PATCH 11/33] Populate AUXV Janani Venkataraman
@ 2014-03-20  9:40 ` Janani Venkataraman
  2014-03-20  9:41 ` [PATCH 13/33] Fetching thread specific Notes Janani Venkataraman
                   ` (22 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:40 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

The file maps details are got from the maps linked list which was
populated in Patch 5 and they are filled as a note in the following
format.

long count     -- how many files are mapped
long page_size -- units for file_ofs
array of [COUNT] elements of
long start
long end
long file_ofs
followed by COUNT filenames in ASCII: "FILE1" NUL "FILE2" NUL...

Signed-off-by: Suzuki K. Poulose <suzuki@in.ibm.com>
Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/elf.c   |   78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/elf32.c |    1 +
 src/elf64.c |    1 +
 3 files changed, 80 insertions(+)

diff --git a/src/elf.c b/src/elf.c
index b7fd6d0..9e3623f 100644
--- a/src/elf.c
+++ b/src/elf.c
@@ -308,6 +308,79 @@ static int get_auxv(int pid, struct core_proc *cp)
 	return ret;
 }
 
+/*
+ * Get File Maps in the following format:
+ * long count     -- how many files are mapped
+ * long page_size -- units for file_ofs
+ * array of [COUNT] elements of
+ * long start
+ * long end
+ * long file_ofs
+ * followed by COUNT filenames in ASCII: "FILE1" NUL "FILE2" NUL...
+ */
+static int get_file_maps(struct core_proc *cp)
+{
+	Elf_Long count = 0;
+	Elf_Long fmap_size = 0, namesz = 0;
+	Elf_Long *fmap;
+	Elf_Long *data_pos;
+	unsigned char *name_pos;
+	int ret;
+	struct maps *map = cp->vmas;
+
+	/*
+	 * Finding the actual size of the file map for which we need
+	 * to know number of VMAS(non zero inode) plus the file name size
+	 * for each of the VMAS(non zero inode.
+	 */
+	while (map) {
+		if (map->inode) {
+			count++;
+			namesz += strlen(map->fname) + 1;
+		}
+		map = map->next;
+	}
+
+	/*
+	 * We add 2 for the count and page_size, 3 * (number of vmas)
+	 * for the start, end and file_ofs and finally the entire size
+	 * of the filenames of all the VMAS.
+	 */
+	fmap_size = ((2 + (3 * count)) * sizeof(Elf_Long))
+				+ (namesz * sizeof(unsigned char));
+
+	fmap = calloc(fmap_size, 1);
+	if (!fmap) {
+		status = errno;
+		gencore_log("Could not allocate memory for file map data\n");
+		return -1;
+	}
+
+	data_pos = fmap + 2;
+	name_pos = (unsigned char *)(fmap + 2 + (count * 3));
+
+	map = cp->vmas;
+	while (map) {
+		if (map->inode) {
+			*data_pos++ = map->src;
+			*data_pos++ = map->dst;
+			*data_pos++ = map->offset;
+
+			strcpy(name_pos, map->fname);
+			name_pos += strlen(map->fname) + 1;
+		}
+		map = map->next;
+	}
+
+	fmap[0] = count;
+	fmap[1] = 1;
+
+	ret = add_note("CORE", NT_FILE, fmap_size, fmap, cp);
+	free(fmap);
+
+	return ret;
+}
+
 int do_elf_coredump(int pid, struct core_proc *cp)
 {
 	int ret;
@@ -327,5 +400,10 @@ int do_elf_coredump(int pid, struct core_proc *cp)
 	if (ret)
 		return -1;
 
+	/* Get File maps */
+	ret = get_file_maps(cp);
+	if (ret)
+		return -1;
+
 	return 0;
 }
diff --git a/src/elf32.c b/src/elf32.c
index 8778bed..0f7c03d 100644
--- a/src/elf32.c
+++ b/src/elf32.c
@@ -35,5 +35,6 @@
 #define Elf_Shdr Elf32_Shdr
 #define Elf_Nhdr Elf32_Nhdr
 #define Elf_prpsinfo compat_elf_prpsinfo
+#define Elf_Long int
 
 #include "elf.c"
diff --git a/src/elf64.c b/src/elf64.c
index d062888..77da222 100644
--- a/src/elf64.c
+++ b/src/elf64.c
@@ -35,5 +35,6 @@
 #define Elf_Shdr Elf64_Shdr
 #define Elf_Nhdr Elf64_Nhdr
 #define Elf_prpsinfo elf_prpsinfo
+#define Elf_Long long
 
 #include "elf.c"


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 13/33] Fetching thread specific Notes
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (11 preceding siblings ...)
  2014-03-20  9:40 ` [PATCH 12/33] Fetch File maps Janani Venkataraman
@ 2014-03-20  9:41 ` Janani Venkataraman
  2014-03-20  9:41 ` [PATCH 14/33] Populating Program Headers Janani Venkataraman
                   ` (21 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:41 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Populates prstatus for each and every thread of the task to be dumped by
accessing their respective /proc/tid/stat.

Fetching the required registers based on the architecture. The architectures
that are handled are X86, S390 and PPC.

We fetch the registers in thread-wise order, as some architectures depend on
the ordering of the notes. (e.g, s390)

Signed-off-by: Suzuki K. Poulose <suzuki@in.ibm.com>
Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.h   |   12 +++
 src/elf-compat.h |   76 +++++++++++++++++++++
 src/elf.c        |  194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/elf32.c      |    1 
 src/elf64.c      |    1 
 5 files changed, 283 insertions(+), 1 deletion(-)

diff --git a/src/coredump.h b/src/coredump.h
index d5562fe..dce6292 100644
--- a/src/coredump.h
+++ b/src/coredump.h
@@ -5,15 +5,27 @@
 #define PGRP 1			/* Index for process group ID */
 #define SID 2			/* Index for session ID */
 #define FLAG 5			/* Index for flags */
+#define UTIME 10		/* Index for scheduled user mode */
+#define STIME 11		/* Index for scheduled user mode */
+#define CUTIME 12		/* Index for scheduled user mode time for a process's waited-for children */
+#define CSTIME 13		/* Index for scheduled kernel mode time for a process's waited-for children */
 #define NICE 15		/* Index for nice value */
 #define THREAD_COUNT_IDX 16	/* Index for number of threads */
+#define SIGPEND 27		/* Index for pending signals for a process */
+#define SIGHOLD 29		/* Index for ignored signals for a process */
 
 #define __ps_thread_count ps_num[THREAD_COUNT_IDX]	/* Process Information */
 #define __ps_ppid ps_num[PPID]				/* Process PID */	
 #define __ps_pgrp ps_num[PGRP]				/* Process Group ID */ 
 #define __ps_sid ps_num[SID]				/* Process Session ID */
 #define __ps_flag ps_num[FLAG]				/* Process Flags */
+#define __ps_utime ps_num[UTIME]			/* Process scheduled user mode */
+#define __ps_stime ps_num[STIME]			/* Process scheduled user mode */
+#define __ps_cutime ps_num[CUTIME]			/* Process scheduled user mode time for a process's waited-for children */
+#define __ps_cstime ps_num[CSTIME]			/* Process scheduled kernel mode time for a process's waited-for children */
 #define __ps_nice ps_num[NICE]				/* Process Nice Value */
+#define __ps_sigpend ps_num[SIGPEND]			/* Process pending signals */
+#define __ps_sighold ps_num[SIGHOLD]			/* Process ignored signals */
 
 /* Status of the dump */
 extern int status;
diff --git a/src/elf-compat.h b/src/elf-compat.h
index 463070a..6399c11 100644
--- a/src/elf-compat.h
+++ b/src/elf-compat.h
@@ -33,6 +33,17 @@ typedef unsigned short compat_id;
 typedef unsigned short compat_id;
 #endif
 
+struct compat_elf_siginfo {
+	int			si_signo;
+	int			si_code;
+	int			si_errno;
+};
+
+struct compat_timeval {
+	int                             tv_sec;
+	int                             tv_usec;
+};
+
 /* Compat structure for PRPS_INFO */
 struct compat_elf_prpsinfo {
 	char				pr_state;
@@ -46,3 +57,68 @@ struct compat_elf_prpsinfo {
 	char				pr_fname[16];
 	char				pr_psargs[ELF_PRARGSZ];
 };
+
+/* Power PC elf_gregset_t */
+#define ELF_NGREG_PPC       48
+typedef unsigned int elf_greg_t32_ppc;
+typedef elf_greg_t32_ppc elf_gregset_t32_ppc[ELF_NGREG_PPC];
+typedef elf_gregset_t32_ppc compat_elf_gregset_t_ppc;
+
+/* x86 elf_gregset_t */
+struct user_regs_struct32_x86 {
+	unsigned int ebx, ecx, edx, esi, edi, ebp, eax;
+	unsigned short ds, __ds, es, __es;
+	unsigned short fs, __fs, gs, __gs;
+	unsigned int orig_eax, eip;
+	unsigned short cs, __cs;
+	unsigned int eflags, esp;
+	unsigned short ss, __ss;
+};
+typedef struct user_regs_struct32_x86 compat_elf_gregset_t_x86;
+
+/* s390 elf_gregset_t */
+#define NUM_GPRS        16
+#define NUM_ACRS        16
+
+typedef struct {
+	unsigned int mask;
+	unsigned int addr;
+} __attribute__((aligned(8))) psw_compat_t;
+
+typedef struct {
+	psw_compat_t psw;
+	unsigned int gprs[NUM_GPRS];
+	unsigned int acrs[NUM_ACRS];
+	unsigned int orig_gpr2;
+} s390_compat_regs;
+
+typedef s390_compat_regs compat_elf_gregset_t_s390;
+
+#if defined(__PPC64__) || defined(__PPC__)
+#define compat_elf_gregset_t compat_elf_gregset_t_ppc
+#endif
+
+#if defined(__s390x__) || defined(__s390__)
+#define compat_elf_gregset_t compat_elf_gregset_t_s390
+#endif
+
+#if defined(__x86_64) || defined(__i386)
+#define compat_elf_gregset_t compat_elf_gregset_t_x86
+#endif
+
+struct compat_elf_prstatus {
+	struct compat_elf_siginfo	pr_info;
+	short				pr_cursig;
+	unsigned int			pr_sigpend;
+	unsigned int			pr_sighold;
+	int				pr_pid;
+	int				pr_ppid;
+	int				pr_pgrp;
+	int				pr_sid;
+	struct compat_timeval           pr_utime;
+	struct compat_timeval           pr_stime;
+	struct compat_timeval           pr_cutime;
+	struct compat_timeval           pr_cstime;
+	compat_elf_gregset_t		pr_reg;
+	int				pr_fpvalid;
+};
diff --git a/src/elf.c b/src/elf.c
index 9e3623f..62dc5a9 100644
--- a/src/elf.c
+++ b/src/elf.c
@@ -30,6 +30,7 @@
 #include <unistd.h>
 #include <sys/uio.h>
 #include <sys/procfs.h>
+#include <sys/ptrace.h>
 #include <linux/elf.h>
 #include "elf-compat.h"
 #include "coredump.h"
@@ -381,9 +382,195 @@ static int get_file_maps(struct core_proc *cp)
 	return ret;
 }
 
-int do_elf_coredump(int pid, struct core_proc *cp)
+/* Getting Registers */
+static int get_regset(int tid, int regset, struct iovec *iov)
+{
+	return ptrace(PTRACE_GETREGSET, tid, regset, iov);
+}
+
+/* Fetching Note */
+static int fetch_note(int regset, const char *name, struct core_proc *cp, int tid)
+{
+	int ret = 0;
+	int size = PAGESIZE;
+	struct iovec iov;
+	void *data;
+	data = malloc(PAGESIZE);
+	if (!data)
+		return -1;
+
+	/*
+	 * The size of regset being fetched may be greater than size,
+	 * which is initially PAGESIZE. The iov_len gets reset to the
+	 * amount of data read by PTRACE_GETREGSET. If the iov_len is
+	 * equal to size, in that case, there is more data to read and
+	 * hence we increase the size and try reading again. The moment
+	 * iov.len is lesser than size, we break out of the loop as all
+	 * the data is read
+	 */
+	while (1) {
+		iov.iov_base = data;
+		iov.iov_len = size;
+		ret = get_regset(cp->t_id[tid], (unsigned int) regset,
+							&iov);
+		if (ret)
+			break;
+		if (iov.iov_len < size)
+			break;
+		size += PAGESIZE;
+		data = realloc(data, size);
+		if (!data)
+			return -1;
+	}
+
+	/* Adding Note */
+	if (ret == 0)
+		ret = add_note(name, regset, iov.iov_len, data, cp);
+
+	free(data);
+
+	return ret;
+}
+
+/* Populates PRSTATUS for the threads */
+static int fill_core_notes(int tid, struct core_proc *cp)
 {
+	/* PRSTATUS */
+	struct iovec iov;
 	int ret;
+	struct Elf_prstatus prstat;
+	struct pid_stat p;
+	char state;
+
+	ret = get_pid_stat(cp->t_id[tid], &p);
+	if (ret)
+		return -1;
+
+	prstat.pr_pid = p.ps_pid;
+	prstat.pr_ppid = p.__ps_ppid;
+	prstat.pr_pgrp = p.__ps_pgrp;
+	prstat.pr_sid = p.__ps_sid;
+	prstat.pr_utime.tv_sec = p.__ps_utime;
+	prstat.pr_stime.tv_sec = p.__ps_stime;
+	prstat.pr_cutime.tv_sec = p.__ps_cutime;
+	prstat.pr_cstime.tv_sec = p.__ps_cstime;
+	prstat.pr_sigpend = p.__ps_sigpend;
+	prstat.pr_sighold = p.__ps_sighold;
+
+	/* General Purpose registers */
+	iov.iov_base = &prstat.pr_reg;
+	iov.iov_len =  sizeof(prstat.pr_reg);
+	ret = get_regset(cp->t_id[tid], NT_PRSTATUS, &iov);
+	if (ret == -1) {
+		state = get_thread_status(cp->t_id[tid]);
+		if (state != 'Z') {
+			status = errno;
+			gencore_log("Failure in fetching General Purpose registers for Thread:%d.\n", tid);
+			return -1;
+		}
+	}
+
+	prstat.pr_info.si_signo = 0;
+
+	/* FP_REGSET */
+	ret = fetch_note(NT_PRFPREG, "CORE", cp, tid);
+	if ( ret == 0)
+		prstat.pr_fpvalid = 1;
+	else
+		prstat.pr_fpvalid = 0;
+		
+	/* Adding PRSTATUS */
+	return add_note("CORE", NT_PRSTATUS, sizeof(prstat),
+						&prstat, cp);
+}
+
+/* X86 Specific Notes */
+static void fetch_x86_notes(struct core_proc *cp, int tid)
+{
+	int notes[] = {
+			NT_X86_XSTATE,
+			NT_386_TLS,
+			0};
+	int i;
+
+	for (i = 0; notes[i]; i++)
+		(void)fetch_note(notes[i], "LINUX", cp, tid);
+}
+
+/* PPC Specific Notes */
+static void fetch_ppc_notes(struct core_proc *cp, int tid)
+{
+	int notes[] = {
+			NT_PPC_VMX,
+			NT_PPC_SPE,
+			NT_PPC_VSX,
+			0};
+	int i;
+
+	for (i = 0; notes[i]; i++)
+		(void)fetch_note(notes[i], "LINUX", cp, tid);
+}
+
+/* S390 Specific Notes */
+static void fetch_s390_notes(struct core_proc *cp, int tid)
+{
+	int notes[] = {
+			NT_S390_HIGH_GPRS,
+			NT_S390_TIMER,
+			NT_S390_LAST_BREAK,
+			NT_S390_SYSTEM_CALL,
+			NT_S390_TODCMP,
+			NT_S390_TODPREG,
+			NT_S390_CTRS,
+			NT_S390_PREFIX,
+			0};
+	int i;
+
+	for (i = 0; notes[i]; i++)
+		(void)fetch_note(notes[i], "LINUX", cp, tid);
+}
+
+/* Fetching thread specific notes */
+static int fetch_thread_notes(struct core_proc *cp)
+{
+	int tid, ret;
+
+	Elf_Ehdr *cp_elf;
+	cp_elf = (Elf_Ehdr *)cp->elf_hdr;
+
+	/*
+	 * The architecture specific notes are optional and they may or may not
+	 * be present. Hence we do not check if we were successful in fetching
+	 * them or not.
+	 */
+
+	for (tid = 0; tid < cp->thread_count; tid++) {
+		ret = fill_core_notes(tid, cp);
+		if (ret)
+			return -1;
+
+		switch (cp_elf->e_machine) {
+		case EM_X86_64:
+		case EM_386:
+			fetch_x86_notes(cp, tid);
+			break;
+		case EM_PPC:
+		case EM_PPC64:
+			fetch_ppc_notes(cp, tid);
+			break;
+		case EM_S390:
+			fetch_s390_notes(cp, tid);
+			break;
+		}
+
+	}
+
+	return 0;
+}
+
+int do_elf_coredump(int pid, struct core_proc *cp)
+{
+	int ret, i;
 
 	/* Fill ELF Header */
 	ret = fill_elf_header(pid, cp);
@@ -405,5 +592,10 @@ int do_elf_coredump(int pid, struct core_proc *cp)
 	if (ret)
 		return -1;
 
+	/* Get the thread specific notes */
+	ret = fetch_thread_notes(cp);
+	if (ret)
+		return -1;
+
 	return 0;
 }
diff --git a/src/elf32.c b/src/elf32.c
index 0f7c03d..8ec287b 100644
--- a/src/elf32.c
+++ b/src/elf32.c
@@ -36,5 +36,6 @@
 #define Elf_Nhdr Elf32_Nhdr
 #define Elf_prpsinfo compat_elf_prpsinfo
 #define Elf_Long int
+#define Elf_prstatus compat_elf_prstatus
 
 #include "elf.c"
diff --git a/src/elf64.c b/src/elf64.c
index 77da222..780e2d4 100644
--- a/src/elf64.c
+++ b/src/elf64.c
@@ -36,5 +36,6 @@
 #define Elf_Nhdr Elf64_Nhdr
 #define Elf_prpsinfo elf_prpsinfo
 #define Elf_Long long
+#define Elf_prstatus elf_prstatus
 
 #include "elf.c"


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 14/33] Populating Program Headers
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (12 preceding siblings ...)
  2014-03-20  9:41 ` [PATCH 13/33] Fetching thread specific Notes Janani Venkataraman
@ 2014-03-20  9:41 ` Janani Venkataraman
  2014-03-20  9:41 ` [PATCH 15/33] Updating Offset Janani Venkataraman
                   ` (20 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:41 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Populates the program headers using memory maps linked list which was
populated in patch 5. The source, size and permissions of the maps are
found out and filled respectively.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.c |    6 +++
 src/coredump.h |    2 +
 src/elf.c      |  108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/elf32.c    |    2 +
 src/elf64.c    |    1 +
 5 files changed, 119 insertions(+)

diff --git a/src/coredump.c b/src/coredump.c
index 0fd6343e..5cccb7a 100644
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -231,6 +231,12 @@ cleanup:
 	if (cp.notes)
 		free_notes(cp.notes);
 
+	if (cp.phdrs)
+		free(cp.phdrs);
+
+	if (cp.phdrs_count)
+		free(cp.shdrs);
+
 	errno = status;
 
 	return ret;
diff --git a/src/coredump.h b/src/coredump.h
index dce6292..a729f16 100644
--- a/src/coredump.h
+++ b/src/coredump.h
@@ -68,4 +68,6 @@ struct core_proc {
 	int elf_class;			/* Elf class of the process */
 	void *elf_hdr;			/* Stores the ELF_header */
 	struct mem_note *notes;		/* Head of Notes */
+	void *shdrs;			/* Extra Program Headers */
+	void *phdrs;			/* Program Headers */
 };
diff --git a/src/elf.c b/src/elf.c
index 62dc5a9..a5a1feb 100644
--- a/src/elf.c
+++ b/src/elf.c
@@ -39,6 +39,11 @@
 
 #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
 
+/* Default alignment for program headers */
+#ifndef ELF_EXEC_PAGESIZE
+#define ELF_EXEC_PAGESIZE PAGESIZE
+#endif
+
 /* Appending the note to the list */
 static void append_note(struct mem_note *new_note, struct core_proc *cp)
 {
@@ -110,6 +115,26 @@ static int add_note(const char *name, int type, unsigned int data_sz, void *data
 	return 0;
 }
 
+/*
+ * Reads first few bytes of the address specified and checks if it is
+ * an ELF by checking the magic number.
+ */
+static int get_elf_hdr_vaddr(int pid, Elf_Ehdr *elf, Elf_Addr addr)
+{
+	int ret;
+	struct iovec local, remote;
+
+	local.iov_base = elf;
+	local.iov_len = sizeof(Elf_Ehdr);
+	remote.iov_base = (void *)addr;
+	remote.iov_len = sizeof(Elf_Ehdr);
+	ret = process_vm_readv(pid, &local, 1, &remote, 1, 0);
+	if (ret == -1)
+		return -1;
+
+	return check_elf_hdr(elf->e_ident);
+}
+
 /* Fetchs ELF header of the executable */
 static int get_elf_hdr_exe_file(int pid, Elf_Ehdr *elf)
 {
@@ -568,6 +593,84 @@ static int fetch_thread_notes(struct core_proc *cp)
 	return 0;
 }
 
+/* Populate Program headers */
+static int get_phdrs(int pid, struct core_proc *cp)
+{
+	int n;
+	struct maps *map = cp->vmas;
+	Elf_Ehdr elf;
+	Elf_Phdr *cp_phdrs;
+	Elf_Shdr *cp_shdrs;
+	Elf_Ehdr *cp_elf;
+	cp_elf = (Elf_Ehdr *)cp->elf_hdr;
+
+	cp->phdrs = calloc(cp->phdrs_count, sizeof(Elf_Phdr));
+	if (!cp->phdrs) {
+		status = errno;
+		gencore_log("Could not allocate memory for Program headers.\n");
+		return -1;
+	}
+
+	cp_phdrs = (Elf_Phdr *)cp->phdrs;
+
+	cp_phdrs[0].p_type = PT_NOTE;
+	cp_phdrs[0].p_offset = 0;
+	cp_phdrs[0].p_vaddr = 0;
+	cp_phdrs[0].p_paddr = 0;
+	/* Will fill the size after filling notes */
+	cp_phdrs[0].p_filesz = 0;
+	cp_phdrs[0].p_memsz = 0;
+
+	n = 1;
+
+	while (map) {
+
+		/* Filling the Program Header Values */
+		cp_phdrs[n].p_type = PT_LOAD;
+		cp_phdrs[n].p_offset = 0;
+		cp_phdrs[n].p_vaddr = map->src;
+		cp_phdrs[n].p_paddr = 0;
+		cp_phdrs[n].p_flags = 0;
+		if (map->r == 'r')
+			cp_phdrs[n].p_flags |= PF_R;
+		if (map->w == 'w')
+			cp_phdrs[n].p_flags |= PF_W;
+		if (map->x == 'x')
+			cp_phdrs[n].p_flags |= PF_X;
+
+		cp_phdrs[n].p_memsz = map->dst - map->src;
+
+		if (!(cp_phdrs[n].p_flags & PF_R))
+			cp_phdrs[n].p_filesz = 0;
+		else if (map->inode &&
+			get_elf_hdr_vaddr(pid, &elf, cp_phdrs[n].p_vaddr) == 0)
+			cp_phdrs[n].p_filesz = ELF_EXEC_PAGESIZE;
+		else
+			cp_phdrs[n].p_filesz = cp_phdrs[n].p_memsz;
+		
+		cp_phdrs[n].p_align = ELF_EXEC_PAGESIZE;
+
+		n++;
+		map = map->next;
+	}
+
+	if (cp->phdrs_count > PN_XNUM) {
+		cp->shdrs = malloc(sizeof(Elf_Shdr));
+		if (!cp->shdrs) {
+			status = errno;
+			gencore_log("Could not allocate memory for Extra Program headers.\n");
+			return -1;
+		}
+		cp_shdrs = (Elf_Shdr *)cp->shdrs;
+		cp_shdrs->sh_type = SHT_NULL;
+		cp_shdrs->sh_size = cp_elf->e_shnum;
+		cp_shdrs->sh_link = cp_elf->e_shstrndx;
+		cp_shdrs->sh_info = cp->phdrs_count;
+	}
+
+	return 0;
+}
+
 int do_elf_coredump(int pid, struct core_proc *cp)
 {
 	int ret, i;
@@ -597,5 +700,10 @@ int do_elf_coredump(int pid, struct core_proc *cp)
 	if (ret)
 		return -1;
 
+	/* Get Program headers */
+	ret = get_phdrs(pid, cp);
+	if (ret)
+		return -1;
+
 	return 0;
 }
diff --git a/src/elf32.c b/src/elf32.c
index 8ec287b..daf9940 100644
--- a/src/elf32.c
+++ b/src/elf32.c
@@ -38,4 +38,6 @@
 #define Elf_Long int
 #define Elf_prstatus compat_elf_prstatus
 
+#define Elf_Addr Elf32_Addr
+
 #include "elf.c"
diff --git a/src/elf64.c b/src/elf64.c
index 780e2d4..651f218 100644
--- a/src/elf64.c
+++ b/src/elf64.c
@@ -37,5 +37,6 @@
 #define Elf_prpsinfo elf_prpsinfo
 #define Elf_Long long
 #define Elf_prstatus elf_prstatus
+#define Elf_Addr Elf64_Addr
 
 #include "elf.c"


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 15/33] Updating Offset
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (13 preceding siblings ...)
  2014-03-20  9:41 ` [PATCH 14/33] Populating Program Headers Janani Venkataraman
@ 2014-03-20  9:41 ` Janani Venkataraman
  2014-03-20  9:41 ` [PATCH 16/33] Writing to core file Janani Venkataraman
                   ` (19 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:41 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Updating offset throughout keeping in mind that they need to be PAGE ALIGNED.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/elf.c |   50 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/src/elf.c b/src/elf.c
index a5a1feb..a101ddf 100644
--- a/src/elf.c
+++ b/src/elf.c
@@ -39,6 +39,8 @@
 
 #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
 
+#define ALIGN(addr, pagesize) (((addr) + (pagesize) - 1) & ~(pagesize - 1))
+
 /* Default alignment for program headers */
 #ifndef ELF_EXEC_PAGESIZE
 #define ELF_EXEC_PAGESIZE PAGESIZE
@@ -617,7 +619,6 @@ static int get_phdrs(int pid, struct core_proc *cp)
 	cp_phdrs[0].p_offset = 0;
 	cp_phdrs[0].p_vaddr = 0;
 	cp_phdrs[0].p_paddr = 0;
-	/* Will fill the size after filling notes */
 	cp_phdrs[0].p_filesz = 0;
 	cp_phdrs[0].p_memsz = 0;
 
@@ -671,6 +672,50 @@ static int get_phdrs(int pid, struct core_proc *cp)
 	return 0;
 }
 
+/* Updating the Offset */
+static void update_offset(struct core_proc *cp)
+{
+	Elf_Long data_offset = 0;
+	struct mem_note *note = cp->notes;
+	int i;
+	Elf_Phdr *cp_phdrs;
+	Elf_Ehdr *cp_elf;
+
+	cp_elf = (Elf_Ehdr *)cp->elf_hdr;
+	cp_phdrs = (Elf_Phdr *)cp->phdrs;
+
+	/* ELF HEADER */
+	data_offset += sizeof(Elf_Ehdr);
+
+	/* Program Headers */
+	data_offset += cp->phdrs_count * sizeof(Elf_Phdr);
+
+	/* Notes */
+	cp_phdrs[0].p_offset = data_offset;
+
+	/* Calucalating entire NOTES size */
+	while (note) {
+		data_offset += note->size;
+		note = note->next;
+	}
+
+	/* Filling PT_NOTE size */
+	cp_phdrs[0].p_filesz = data_offset - cp_phdrs[0].p_offset;
+
+	data_offset = ALIGN(data_offset, ELF_EXEC_PAGESIZE);
+
+	/* Populating offsets of Program Headers */
+	for (i = 1; i < cp->phdrs_count; i++) {
+		cp_phdrs[i].p_offset = data_offset;
+		data_offset += cp_phdrs[i].p_filesz;
+		data_offset = ALIGN(data_offset, ELF_EXEC_PAGESIZE);
+	}
+
+	/* Filling extra program header offset if phnum > PN_XNUM */
+	if (cp->phdrs_count > PN_XNUM)
+		cp_elf->e_shoff = data_offset;
+}
+
 int do_elf_coredump(int pid, struct core_proc *cp)
 {
 	int ret, i;
@@ -705,5 +750,8 @@ int do_elf_coredump(int pid, struct core_proc *cp)
 	if (ret)
 		return -1;
 
+	/* Updating offset */
+	update_offset(cp);
+
 	return 0;
 }


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 16/33] Writing to core file
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (14 preceding siblings ...)
  2014-03-20  9:41 ` [PATCH 15/33] Updating Offset Janani Venkataraman
@ 2014-03-20  9:41 ` Janani Venkataraman
  2014-03-20  9:41 ` [PATCH 17/33] Daemonizing the Process Janani Venkataraman
                   ` (18 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:41 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Writing the core details onto the corefile namely the ELF_HEADER, the
PROGRAM_HEADERS, the NOTES and the actual MEMORY.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.c |    5 ++++
 src/coredump.h |    1 +
 src/elf.c      |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 76 insertions(+)

diff --git a/src/coredump.c b/src/coredump.c
index 5cccb7a..a6bcaae 100644
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -206,6 +206,9 @@ int do_coredump(int pid, char *core_file)
 	if (ret == -1)
 		goto cleanup;
 
+	/* Initialise core file name */
+	cp.corefile = core_file;
+
 	/* Do elf_dump */
 	if (cp.elf_class == ELFCLASS32)
 		ret = do_elf32_coredump(pid, &cp);
@@ -295,6 +298,8 @@ int main(int argc, char *argv[])
 
 		if (ret == -1)
 			gencore_log("Failed to create core file.\n");
+		else
+			fprintf(stdout, "Created core file.\n");
 	}
 
 	return ret;
diff --git a/src/coredump.h b/src/coredump.h
index a729f16..334d930 100644
--- a/src/coredump.h
+++ b/src/coredump.h
@@ -70,4 +70,5 @@ struct core_proc {
 	struct mem_note *notes;		/* Head of Notes */
 	void *shdrs;			/* Extra Program Headers */
 	void *phdrs;			/* Program Headers */
+	char *corefile;			/* Name of the core file */
 };
diff --git a/src/elf.c b/src/elf.c
index a101ddf..5b09596 100644
--- a/src/elf.c
+++ b/src/elf.c
@@ -716,6 +716,71 @@ static void update_offset(struct core_proc *cp)
 		cp_elf->e_shoff = data_offset;
 }
 
+/* Writing into corefile */
+static int write_to_core(int pid, struct core_proc *cp)
+{
+	FILE *fcore;
+	int i, ret;
+	unsigned char *mem_segs;
+	struct iovec local, remote;
+	struct mem_note *note = cp->notes;
+	Elf_Phdr *cp_phdrs;
+	Elf_Ehdr *cp_elf;
+
+	cp_elf = (Elf_Ehdr *)cp->elf_hdr;
+	cp_phdrs = (Elf_Phdr *)cp->phdrs;
+
+	/* Writing to File */
+	fcore = fopen(cp->corefile, "wb");
+	if (fcore == NULL) {
+		status = errno;
+		gencore_log("Could not open: %s.\n", cp->corefile);
+		return -1;
+	}
+
+	/* ELF HEADER */
+	fwrite(cp->elf_hdr, sizeof(Elf_Ehdr), 1, fcore);
+
+	/* PROGRAM HEAERS */
+	for (i = 0; i < cp->phdrs_count; i++)
+		fwrite(&cp_phdrs[i], sizeof(Elf_Phdr), 1, fcore);
+
+	/* NOTES */
+	while (note) {
+		fwrite(note->notebuf, note->size, 1, fcore);
+		note = note->next;
+	}
+
+	/* MEMORY */
+	for (i = 1; i < cp->phdrs_count; i++) {
+		mem_segs = malloc(cp_phdrs[i].p_filesz * sizeof(unsigned char));
+		local.iov_base = mem_segs;
+		local.iov_len = cp_phdrs[i].p_filesz;
+		remote.iov_base = (void *) cp_phdrs[i].p_vaddr;
+		remote.iov_len = cp_phdrs[i].p_filesz;
+		if ((cp_phdrs[i].p_flags & PF_R))
+			ret = process_vm_readv(pid, &local, 1, &remote, 1, 0);
+		if (ret == -1) {
+			status = errno;
+			gencore_log("Could not read memory from address: %llx.\n", cp_phdrs[i].p_vaddr);
+			fclose(fcore);
+			free(mem_segs);
+			return -1;
+		}
+
+		fseek(fcore, cp_phdrs[i].p_offset, SEEK_SET);
+		ret = fwrite(mem_segs, cp_phdrs[i].p_filesz, 1, fcore);
+		free(mem_segs);
+	}
+
+	/* Writing extra program headers if cp.phdrs_count > PN_XNUM */
+	if (cp->phdrs_count > PN_XNUM)
+		fwrite(cp->shdrs, sizeof(Elf_Shdr), 1, fcore);
+
+	fclose(fcore);
+	return 0;
+}
+
 int do_elf_coredump(int pid, struct core_proc *cp)
 {
 	int ret, i;
@@ -753,5 +818,10 @@ int do_elf_coredump(int pid, struct core_proc *cp)
 	/* Updating offset */
 	update_offset(cp);
 
+	/* Writing to core */
+	ret = write_to_core(pid, cp);
+	if (ret)
+		return -1;
+
 	return 0;
 }


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 17/33] Daemonizing the Process
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (15 preceding siblings ...)
  2014-03-20  9:41 ` [PATCH 16/33] Writing to core file Janani Venkataraman
@ 2014-03-20  9:41 ` Janani Venkataraman
  2014-03-20  9:41 ` [PATCH 18/33] Socket operations Janani Venkataraman
                   ` (17 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:41 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

For the purpose of a self dump, we start a daemon which accepts requests and
acts like a server. This method was adapted from the CRIU self dump
application.

Checks if the process is running as root, if yes daemonizes it through the
daemon library call and opens a log file to log in the events of the daemon.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.c |   35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/src/coredump.c b/src/coredump.c
index a6bcaae..09fb8da 100644
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -29,6 +29,9 @@
 #include <dirent.h>
 #include <errno.h>
 #include <elf.h>
+#include <errno.h>
+#include <syslog.h>
+#include <signal.h>
 #include <sys/ptrace.h>
 #include <coredump.h>
 
@@ -50,6 +53,13 @@ void gencore_log(char *fmt, ...)
 /* Core process object */
 struct core_proc cp;
 
+#ifndef GENCORE_DAEMON_LOGFILE
+#define GENCORE_DAEMON_LOGFILE "/var/log/gencored.log"
+#endif
+
+/* PID of Daemon */
+int pid_log;
+
 /* Initialised core process members */
 void init_core(void)
 {
@@ -248,6 +258,31 @@ cleanup:
 /* Daemon for self dump */
 int daemon_dump(void)
 {
+	/* Check if daemon is running as root */
+	if (geteuid()) {
+		fprintf(stderr, "Run the daemon as root.\n");
+		return -1;
+	}
+
+	/* Daemonizing it */
+	if (daemon(0, 0)) {
+		fprintf(stderr, "Daemon not up %s.", strerror(errno));
+		return -1;
+	}
+
+	/* Get the PID of the daemon */
+	pid_log = getpid();
+
+	fp_log = fopen(GENCORE_DAEMON_LOGFILE, "w+");
+	if (fp_log == NULL) {
+		openlog("gencore_daemon_log", LOG_PID|LOG_CONS, LOG_USER);
+		syslog(LOG_DAEMON, "Could not open: %s.\n",
+					GENCORE_DAEMON_LOGFILE);
+		closelog();
+		return -1;
+	}
+
+	fclose(fp_log);
 	return 0;
 }
 


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 18/33] Socket operations
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (16 preceding siblings ...)
  2014-03-20  9:41 ` [PATCH 17/33] Daemonizing the Process Janani Venkataraman
@ 2014-03-20  9:41 ` Janani Venkataraman
  2014-03-20  9:41 ` [PATCH 19/33] Block till request Janani Venkataraman
                   ` (16 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:41 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Creates a file socket using socket passing PF_UNIX, binds and then listens on
the connection.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/Makefile.am |    3 +-
 src/coredump.c  |  110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 112 insertions(+), 1 deletion(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index 90d8b25..b9b2e9b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,7 @@
 AUTOMAKE_OPTIONS = foreign
 HAVE_SYSTEMD_SOCKET_SUPPORT = 0
-CFLAGS += -I. -DHAVE_SYSTEMD_SOCKET_SUPPORT='$(HAVE_SYSTEMD_SOCKET_SUPPORT)'
+SOCKET_PATH = /var/run/gencored.socket
+CFLAGS += -I. -DHAVE_SYSTEMD_SOCKET_SUPPORT='$(HAVE_SYSTEMD_SOCKET_SUPPORT)' -DSOCKET_PATH='"$(SOCKET_PATH)"'
 
 bin_PROGRAMS = gencore
 gencore_SOURCES = coredump.c proc.c elf32.c elf64.c
diff --git a/src/coredump.c b/src/coredump.c
index 09fb8da..c992c66 100644
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -33,8 +33,15 @@
 #include <syslog.h>
 #include <signal.h>
 #include <sys/ptrace.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <coredump.h>
 
+/* Main Socket */
+int socket_fd;
+
 /* For logging all the messages */
 FILE *fp_log;
 
@@ -255,9 +262,98 @@ cleanup:
 	return ret;
 }
 
+/* Creating a Unix socket */
+int create_socket(void)
+{
+	socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
+	if (socket_fd < 0) {
+		gencore_log("[%d]: Could not create a socket:%s.\n",
+					pid_log, strerror(errno));
+		return -1;
+	}
+
+	gencore_log("[%d]: Created socket.\n", pid_log);
+
+	return 0;
+}
+
+/* Binding the socket to a address */
+int bind_socket(void)
+{
+	struct sockaddr_un address;
+	struct stat buffer;
+	if (stat(SOCKET_PATH, &buffer) == 0)
+		unlink(SOCKET_PATH);
+
+	memset(&address, 0, sizeof(struct sockaddr_un));
+
+	address.sun_family = PF_FILE;
+	strcpy(address.sun_path, SOCKET_PATH);
+
+	if (bind(socket_fd, (struct sockaddr *) &address,
+			sizeof(struct sockaddr_un)) != 0) {
+		gencore_log("[%d]: Could not bind:%s.\n", pid_log,
+							strerror(errno));
+		close(socket_fd);
+		return -1;
+	}
+
+	if (chmod(SOCKET_PATH, S_IROTH | S_IWOTH
+						| S_IRUSR | S_IWUSR)) {
+		gencore_log("[%d]: Could not change permissions of socket:%s.\n",
+						pid_log, strerror(errno));
+		close(socket_fd);
+		return -1;
+	}
+
+	gencore_log("[%d]: Bind done.\n", pid_log);
+
+	return 0;
+}
+
+/* Listen for connections */
+int listen_conn(void)
+{
+	if (listen(socket_fd, 5) != 0) {
+		gencore_log("[%d]: Could not listen:%s.\n", pid_log,
+							strerror(errno));
+		close(socket_fd);
+		return -1;
+	}
+
+	gencore_log("[%d]: Listening.\n", pid_log);
+
+	return 0;
+}
+
+/* Setting up server */
+int setup_server(void)
+{
+	int ret;
+
+	/* Create Socket */
+	ret = create_socket();
+	if (ret)
+		return -1;
+
+	/* Bind Socket */
+	ret = bind_socket();
+	if (ret)
+		return -1;
+
+	/* Listen for connections */
+	ret = listen_conn();
+	if (ret)
+		return -1;
+
+	return 0;
+}
+
 /* Daemon for self dump */
 int daemon_dump(void)
 {
+	int ret;
+
 	/* Check if daemon is running as root */
 	if (geteuid()) {
 		fprintf(stderr, "Run the daemon as root.\n");
@@ -282,7 +378,21 @@ int daemon_dump(void)
 		return -1;
 	}
 
+	/* Setting up server */
+	ret = setup_server();
+	if (ret)
+		goto cleanup;
+
+	/* Flush the log */
+	fflush(fp_log);
+
+cleanup:
+
 	fclose(fp_log);
+
+	if (ret == -1)
+		return -1;
+
 	return 0;
 }
 


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 19/33] Block till request
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (17 preceding siblings ...)
  2014-03-20  9:41 ` [PATCH 18/33] Socket operations Janani Venkataraman
@ 2014-03-20  9:41 ` Janani Venkataraman
  2014-03-20  9:41 ` [PATCH 20/33] Handling Requests Janani Venkataraman
                   ` (15 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:41 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Block until input arrives on the socket.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.c |   45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/src/coredump.c b/src/coredump.c
index c992c66..d93f4b2 100644
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -349,6 +349,38 @@ int setup_server(void)
 	return 0;
 }
 
+/* Blocking on a request */
+int block_on_request(void)
+{
+	fd_set read;
+
+	do {
+		/* Initialise */
+		FD_ZERO(&read);
+		FD_SET(socket_fd, &read);
+
+		gencore_log("[%d]: Waiting on incoming request.\n", pid_log);
+
+		if (select(socket_fd + 1, &read, NULL, NULL, NULL) <= 0) {
+			/*
+			 * EINTR just means a signal is caught and hence, we need not
+			 * terminate for this error.
+			 */
+			if (errno != EINTR) {
+				gencore_log("[%d]: Error while waiting for connection requests.\n",
+						pid_log, strerror(errno));
+				close(socket_fd);
+				return -1;
+			}
+		}
+
+	} while(FD_ISSET(socket_fd, &read) == 0);
+
+	gencore_log("[%d]: Request found.\n", pid_log);
+
+	return 0;
+}
+
 /* Daemon for self dump */
 int daemon_dump(void)
 {
@@ -386,6 +418,19 @@ int daemon_dump(void)
 	/* Flush the log */
 	fflush(fp_log);
 
+	while (1) {
+
+		/* Blocks on request */
+		ret = block_on_request();
+		if (ret)
+			goto cleanup;
+
+		/* Flush the log */
+		fflush(fp_log);
+	}
+
+	return 0;
+
 cleanup:
 
 	fclose(fp_log);


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 20/33] Handling Requests
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (18 preceding siblings ...)
  2014-03-20  9:41 ` [PATCH 19/33] Block till request Janani Venkataraman
@ 2014-03-20  9:41 ` Janani Venkataraman
  2014-03-20  9:41 ` [PATCH 21/33] Get Clients PID Janani Venkataraman
                   ` (14 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:41 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Accepting requests and then spawning a new thread to service them.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.c |  110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 110 insertions(+)
 mode change 100644 => 100755 src/coredump.c

diff --git a/src/coredump.c b/src/coredump.c
old mode 100644
new mode 100755
index d93f4b2..fadb7cd
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -42,6 +42,11 @@
 /* Main Socket */
 int socket_fd;
 
+/* Accepted Socket */
+int new_sock;
+
+#define CORE_FILE_NAME_SZ 1000	/* Size of core file name */
+
 /* For logging all the messages */
 FILE *fp_log;
 
@@ -381,6 +386,100 @@ int block_on_request(void)
 	return 0;
 }
 
+/* Handles a SIGCHILD */
+void sigchild_handler(int sig)
+{
+	int pid;
+
+	pid = waitpid(0, &status, WNOHANG);
+
+	gencore_log("[%d]: Request handled by child with PID:%d and exited.\n",
+				pid_log, pid);
+}
+
+/* Sends message to client */
+int send_reply(int err)
+{
+	if (write(new_sock, &err , sizeof(err)) == -1) {
+		gencore_log("[%d]: Could not send message:%s\n",
+					pid_log, strerror(errno));
+		return -1;
+	}
+
+	gencore_log("[%d]: Message sent:%d\n", pid_log, err);
+
+	return 0;
+}
+
+/* Receive message from client */
+int receive_core_filename(char *core_file)
+{
+	memset(core_file, 0, CORE_FILE_NAME_SZ);
+	if (read(new_sock, core_file , CORE_FILE_NAME_SZ) == -1) {
+		send_reply(errno);
+		gencore_log("[%d]: Could not get Core file name:%s\n",
+					pid_log, strerror(errno));
+		return -1;
+	}
+
+	gencore_log("[%d]: Core file path received:%s\n", pid_log,
+						core_file);
+	/* Sending the acknowledgment */
+	send_reply(0);
+
+	return 0;
+}
+
+/* Services requests */
+int service_request(void)
+{
+	int ret;
+	char core_file[CORE_FILE_NAME_SZ];
+
+	/* Receive the message */
+	ret = receive_core_filename(core_file);
+	if (ret)
+		goto cleanup;
+
+cleanup:
+	close(new_sock);
+	if (ret == -1)
+		exit(EXIT_FAILURE);
+
+	exit(EXIT_SUCCESS);
+}
+
+/* Handles new requests */
+int handle_request(void)
+{
+	int pid_new;
+	struct sockaddr_un client_address;
+	socklen_t client_size = sizeof(client_address);
+
+	new_sock = accept(socket_fd, (struct sockaddr *) &client_address,
+							&client_size);
+	if (new_sock < 0) {
+		gencore_log("[%d]: Could not accept:%s\n", pid_log,
+							strerror(errno));
+		close(socket_fd);
+		fclose(fp_log);
+		return -1;
+	}
+
+	gencore_log("[%d]: Accepted.\n", pid_log);
+
+	gencore_log("[%d]: Handling request.\n", pid_log);
+
+	/* New thread to service request */
+	pid_new = fork();
+	if (pid_new == 0) {
+		pid_log = getpid();
+		service_request();
+	}
+
+	return 0;
+}
+
 /* Daemon for self dump */
 int daemon_dump(void)
 {
@@ -418,6 +517,9 @@ int daemon_dump(void)
 	/* Flush the log */
 	fflush(fp_log);
 
+	/* SIGCHILD - Signal handler */
+	signal(SIGCHLD, sigchild_handler);
+
 	while (1) {
 
 		/* Blocks on request */
@@ -427,6 +529,14 @@ int daemon_dump(void)
 
 		/* Flush the log */
 		fflush(fp_log);
+
+		/* Handle new connections */
+		ret = handle_request();
+		if (ret)
+			goto cleanup;
+
+		/* Flush the log */
+		fflush(fp_log);
 	}
 
 	return 0;


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 21/33] Get Clients PID
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (19 preceding siblings ...)
  2014-03-20  9:41 ` [PATCH 20/33] Handling Requests Janani Venkataraman
@ 2014-03-20  9:41 ` Janani Venkataraman
  2014-03-20  9:41 ` [PATCH 22/33] Dump the task Janani Venkataraman
                   ` (13 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:41 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Get the Clients PID using getsockopt. This is done for security reasons. So
that we dont get any malicious dump requests.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.c |   22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/src/coredump.c b/src/coredump.c
index fadb7cd..599a912 100755
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -22,6 +22,7 @@
  *      Suzuki K. Poulose <suzuki@in.ibm.com>
  */
 
+#define _GNU_SOURCE
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
@@ -430,17 +431,38 @@ int receive_core_filename(char *core_file)
 	return 0;
 }
 
+/* Get client details */
+int get_client_pid(struct ucred *client_info)
+{
+	socklen_t len = sizeof(struct ucred);
+	if (getsockopt(new_sock, SOL_SOCKET, SO_PEERCRED,
+				client_info, &len)) {
+		send_reply(errno);
+		gencore_log("[%d]: Can't get credentials of the client:%s\n",
+				pid_log, strerror(errno));
+		return -1;
+	}
+
+	return 0;
+}
+
 /* Services requests */
 int service_request(void)
 {
 	int ret;
 	char core_file[CORE_FILE_NAME_SZ];
+	struct ucred client_info;
 
 	/* Receive the message */
 	ret = receive_core_filename(core_file);
 	if (ret)
 		goto cleanup;
 
+	/* Fetch client PID */
+	ret = get_client_pid(&client_info);
+	if (ret)
+		goto cleanup;
+
 cleanup:
 	close(new_sock);
 	if (ret == -1)


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 22/33] Dump the task
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (20 preceding siblings ...)
  2014-03-20  9:41 ` [PATCH 21/33] Get Clients PID Janani Venkataraman
@ 2014-03-20  9:41 ` Janani Venkataraman
  2014-03-20  9:42 ` [PATCH 23/33] Handling SIG TERM of the daemon Janani Venkataraman
                   ` (12 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:41 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Now we have the PID and the absolute or relative path of the core. We now call
the do_coredump function with the appropriate parameters.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.c |   60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/src/coredump.c b/src/coredump.c
index 599a912..72ba8d8 100755
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -446,6 +446,61 @@ int get_client_pid(struct ucred *client_info)
 	return 0;
 }
 
+/* Dumps the client process */
+int dump_task(struct ucred *client_info, char *core_file)
+{
+
+	char filename[40], cwd[CORE_FILE_NAME_SZ], corefile[CORE_FILE_NAME_SZ];
+	memset(filename, 0, 40);
+	memset(cwd, 0, CORE_FILE_NAME_SZ);
+	memset(corefile, 0, CORE_FILE_NAME_SZ);
+
+	if (setgid(client_info->gid)) {
+		send_reply(errno);
+		gencore_log("[%d]: Could not change GID:%s\n",
+				pid_log, strerror(errno));
+		return -1;
+	}
+
+	if (setuid(client_info->uid)) {
+		send_reply(errno);
+		gencore_log("[%d]: Could not change UID:%s\n",
+				pid_log, strerror(errno));
+		return -1;
+	}
+
+	/* Checking if UID was changed */
+	if (geteuid() != client_info->uid) {
+		send_reply(errno);
+		gencore_log("[%d]: Could not change UID:%s\n",
+				pid_log, strerror(errno));
+		return -1;
+	}
+
+	/* Converting the path to absolute path */
+	if (core_file[0] != '/') {
+		snprintf(filename, 40, "/proc/%d/cwd", client_info->pid);
+		readlink(filename, cwd, CORE_FILE_NAME_SZ);
+		snprintf(corefile, CORE_FILE_NAME_SZ, "%s/%s", cwd, core_file);
+	} else
+		strcpy(corefile, core_file);
+
+	if (do_coredump(client_info->pid, (char *)corefile)) {
+		send_reply(errno);
+		gencore_log("[%d]: Could not create core file %s.\n",
+						pid_log, corefile);
+		fflush(fp_log);
+		return -1;
+	}
+
+	gencore_log("[%d]: Core file %s created.\n", pid_log,
+							corefile);
+
+	send_reply(0);
+
+	return 0;
+}
+
 /* Services requests */
 int service_request(void)
 {
@@ -463,6 +518,11 @@ int service_request(void)
 	if (ret)
 		goto cleanup;
 
+	/* Dump process */
+	ret = dump_task(&client_info, core_file);
+	if (ret)
+		goto cleanup;
+
 cleanup:
 	close(new_sock);
 	if (ret == -1)


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 23/33] Handling SIG TERM of the daemon
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (21 preceding siblings ...)
  2014-03-20  9:41 ` [PATCH 22/33] Dump the task Janani Venkataraman
@ 2014-03-20  9:42 ` Janani Venkataraman
  2014-03-20  9:42 ` [PATCH 24/33] Handling SIG TERM of the child Janani Venkataraman
                   ` (11 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:42 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

We handle SIGTERM on the daemon, by closing the socket opened for that
connection.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.c |   16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/src/coredump.c b/src/coredump.c
index 72ba8d8..c0da457 100755
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -562,6 +562,17 @@ int handle_request(void)
 	return 0;
 }
 
+/* Handles Signals to the Daemon */
+void sig_daemon_handler(int sig)
+{
+	close(socket_fd);
+	unlink(SOCKET_PATH);
+
+	gencore_log("[%d]: Cleanup done and daemon exiting.\n", pid_log);
+
+	fclose(fp_log);
+}
+
 /* Daemon for self dump */
 int daemon_dump(void)
 {
@@ -602,6 +613,11 @@ int daemon_dump(void)
 	/* SIGCHILD - Signal handler */
 	signal(SIGCHLD, sigchild_handler);
 
+	/* Terminate Daemon - signal handler */
+	signal(SIGTERM, sig_daemon_handler);
+	signal(SIGSEGV, sig_daemon_handler);
+	signal(SIGPIPE, sig_daemon_handler);
+
 	while (1) {
 
 		/* Blocks on request */


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 24/33] Handling SIG TERM of the child
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (22 preceding siblings ...)
  2014-03-20  9:42 ` [PATCH 23/33] Handling SIG TERM of the daemon Janani Venkataraman
@ 2014-03-20  9:42 ` Janani Venkataraman
  2014-03-20  9:42 ` [PATCH 25/33] Systemd Socket ID retrieval Janani Venkataraman
                   ` (10 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:42 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

We handle SIGTERM on the child, by sending a message to the client and then
closing the socket opened for that connection.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.c |   17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/src/coredump.c b/src/coredump.c
index c0da457..ab120b9 100755
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -501,6 +501,18 @@ int dump_task(struct ucred *client_info, char *core_file)
 	return 0;
 }
 
+/* Handles signals to the child */
+void sig_handler_service_proc(int sig)
+{
+	if (sig != SIGPIPE)
+		send_reply(EINTR);
+	close(new_sock);
+
+	gencore_log("[%d]: Cleanup done and child exiting.\n", pid_log);
+
+	fflush(fp_log);
+}
+
 /* Services requests */
 int service_request(void)
 {
@@ -508,6 +520,11 @@ int service_request(void)
 	char core_file[CORE_FILE_NAME_SZ];
 	struct ucred client_info;
 
+	/* Handles stopping of the servicing process */
+	signal(SIGTERM, sig_handler_service_proc);
+	signal(SIGSEGV, sig_handler_service_proc);
+	signal(SIGPIPE, sig_handler_service_proc);
+
 	/* Receive the message */
 	ret = receive_core_filename(core_file);
 	if (ret)


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 25/33] Systemd Socket ID retrieval
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (23 preceding siblings ...)
  2014-03-20  9:42 ` [PATCH 24/33] Handling SIG TERM of the child Janani Venkataraman
@ 2014-03-20  9:42 ` Janani Venkataraman
  2014-03-20  9:42 ` [PATCH 26/33] [libgencore] Setting up Connection Janani Venkataraman
                   ` (9 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:42 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

The socket created by systemd, waits for connections. Once it accepts a
connection, it starts the service which handles the request for a dump.

>From this service, we fetch the socket ID and perform the dump.

This is not functional yet, due to the absence of the sd-daemon.h header file.
For this we need to have the correct version of systemd which has this socket
option enabled.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.c |   32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/src/coredump.c b/src/coredump.c
index ab120b9..98a7146 100755
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -39,6 +39,9 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <coredump.h>
+#if HAVE_SYSTEMD_SOCKET_SUPPORT
+#include <sd-daemon.h>
+#endif
 
 /* Main Socket */
 int socket_fd;
@@ -670,6 +673,35 @@ cleanup:
 /* Systemd socket for self dump */
 int socket_dump(void)
 {
+	int n, ret;
+	char core_file[CORE_FILE_NAME_SZ];
+	struct ucred client_info;
+
+	/* Fetching the Socket ID from systemd */
+	n = sd_listen_fds(0);
+	if (n > 1) {
+		gencore_log("Too many file descriptors received.\n");
+		return -1;
+	} else if (n == 1)
+		new_sock = SD_LISTEN_FDS_START + 0;
+	else
+		return -1;
+
+	/* Receive the message */
+	ret = receive_core_filename(core_file);
+	if (ret)
+		return -1;
+
+	/* Fetch client PID */
+	ret = get_client_pid(&client_info);
+	if (ret)
+		return -1;
+
+	/* Dump process */
+	ret = dump_task(&client_info, core_file);
+	if (ret)
+		return -1;
+
 	return 0;
 }
 #endif


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 26/33] [libgencore] Setting up Connection
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (24 preceding siblings ...)
  2014-03-20  9:42 ` [PATCH 25/33] Systemd Socket ID retrieval Janani Venkataraman
@ 2014-03-20  9:42 ` Janani Venkataraman
  2014-03-20  9:42 ` [PATCH 27/33] [libgencore] Request for dump Janani Venkataraman
                   ` (8 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:42 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Creating a socket and setting up a connection with the server(daemon).

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/Makefile.am |    4 +++
 src/client.c    |   70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 74 insertions(+)
 create mode 100644 src/client.c

diff --git a/src/Makefile.am b/src/Makefile.am
index b9b2e9b..a1d57ca 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,6 +3,10 @@ HAVE_SYSTEMD_SOCKET_SUPPORT = 0
 SOCKET_PATH = /var/run/gencored.socket
 CFLAGS += -I. -DHAVE_SYSTEMD_SOCKET_SUPPORT='$(HAVE_SYSTEMD_SOCKET_SUPPORT)' -DSOCKET_PATH='"$(SOCKET_PATH)"'
 
+lib_LTLIBRARIES = libgencore.la
+libgencore_la_LDFLAGS = -fPIC
+libgencore_la_SOURCES = client.c
+
 bin_PROGRAMS = gencore
 gencore_SOURCES = coredump.c proc.c elf32.c elf64.c
 
diff --git a/src/client.c b/src/client.c
new file mode 100644
index 0000000..cddaf94
--- /dev/null
+++ b/src/client.c
@@ -0,0 +1,70 @@
+/*
+ * Client interface for selfdump.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2013
+ *
+ * Authors:
+ *      Janani Venkataraman <jananve@in.ibm.com>
+ */
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+int setup_connection(void)
+{
+	int socket_fd;
+	struct sockaddr_un address;
+	socklen_t len = sizeof(struct sockaddr_un);
+
+	/* Creating the socket */
+	socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
+	if (socket_fd < 0)
+		return -1;
+
+	memset(&address, 0, len);
+
+	address.sun_family = PF_FILE;
+	strcpy(address.sun_path, SOCKET_PATH);
+
+	/* Connecting to the server */
+	if (connect(socket_fd, (struct sockaddr *) &address, len)) {
+		close(socket_fd);
+		return -1;
+	}
+
+	return socket_fd;
+}
+
+int gencore(char *corefile)
+{
+	int socket, ret;
+
+	/* Socket operation */
+	socket = setup_connection();
+	if (socket == -1) {
+		ret = errno;
+		goto cleanup;
+	}
+
+cleanup:
+
+	return ret;
+}


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 27/33] [libgencore] Request for dump
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (25 preceding siblings ...)
  2014-03-20  9:42 ` [PATCH 26/33] [libgencore] Setting up Connection Janani Venkataraman
@ 2014-03-20  9:42 ` Janani Venkataraman
  2014-03-20  9:43 ` [PATCH 28/33] Man pages Janani Venkataraman
                   ` (7 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:42 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Request for a self dump and wait for an acknowledgement first and then a
response about the status of the dump.

  --------    gencore(file_name) --------
 |        |   ----------------> |        |
 |        |   ack(errno)        |        |
 | CLIENT |   <---------------- | SERVER |
 |        |   status(errno)     |(daemon)|
 |        |   <---------------- |        |
  --------                       --------

a) The client connects to the server(daemon)

b) Once the connection is accepted, request for dump is sent. This request
contains the file name where the dump is to be saved.

c) Once the request is sent, the client waits for an acknowledgment from the
server, that it has received the message.

d) Then the client waits for the status response from the server which either
is a sucess or a failure. If it is a failure, the correct errno is sent back.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/Makefile.am |    1 +
 src/client.c    |   51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gencore.h   |    1 +
 3 files changed, 53 insertions(+)
 create mode 100644 src/gencore.h

diff --git a/src/Makefile.am b/src/Makefile.am
index a1d57ca..c8a52b7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,6 +3,7 @@ HAVE_SYSTEMD_SOCKET_SUPPORT = 0
 SOCKET_PATH = /var/run/gencored.socket
 CFLAGS += -I. -DHAVE_SYSTEMD_SOCKET_SUPPORT='$(HAVE_SYSTEMD_SOCKET_SUPPORT)' -DSOCKET_PATH='"$(SOCKET_PATH)"'
 
+include_HEADERS = gencore.h
 lib_LTLIBRARIES = libgencore.la
 libgencore_la_LDFLAGS = -fPIC
 libgencore_la_SOURCES = client.c
diff --git a/src/client.c b/src/client.c
index cddaf94..8d078b7 100644
--- a/src/client.c
+++ b/src/client.c
@@ -27,6 +27,7 @@
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
+#include <gencore.h>
 
 int setup_connection(void)
 {
@@ -53,6 +54,51 @@ int setup_connection(void)
 	return socket_fd;
 }
 
+/* Sends message to client */
+int send_core_filename(int socket_fd, char *corefile)
+{
+	if (write(socket_fd, corefile , strlen(corefile) + 1) == -1)
+		return errno;
+
+	return 0;
+}
+
+/* Receive message from client */
+int receive_reply(int socket_fd)
+{
+	int reply;
+
+	if (read(socket_fd, &reply , sizeof(reply)) == -1)
+		return errno;
+
+	return reply;
+}
+
+int dump_request(int socket_fd, char *corefile)
+{
+	int ret;
+
+	/* Sends request */
+	ret = send_core_filename(socket_fd, corefile);
+	if (ret)
+		goto cleanup;
+
+	/* Receives acknowledgment */
+	ret = receive_reply(socket_fd);
+	if (ret)
+		goto cleanup;
+
+	/* Receives status */
+	ret = receive_reply(socket_fd);
+	if (ret)
+		goto cleanup;
+
+cleanup:
+	close(socket_fd);
+
+	return ret;
+}
+
 int gencore(char *corefile)
 {
 	int socket, ret;
@@ -64,6 +110,11 @@ int gencore(char *corefile)
 		goto cleanup;
 	}
 
+	/* Asks for a self dump */
+	ret = dump_request(socket, corefile);
+	if (ret)
+		goto cleanup;
+
 cleanup:
 
 	return ret;
diff --git a/src/gencore.h b/src/gencore.h
new file mode 100644
index 0000000..8ad0ca8
--- /dev/null
+++ b/src/gencore.h
@@ -0,0 +1 @@
+int gencore(char *corefile);


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 28/33] Man pages
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (26 preceding siblings ...)
  2014-03-20  9:42 ` [PATCH 27/33] [libgencore] Request for dump Janani Venkataraman
@ 2014-03-20  9:43 ` Janani Venkataraman
  2014-03-20  9:43 ` [PATCH 29/33] Automake files for the doc folder Janani Venkataraman
                   ` (6 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

We have two man pages. One for the command gencore and the second for the
library interface(gencore API) which can be called by the client.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 doc/gencore.1 |   31 +++++++++++++++++++++++++++++++
 doc/gencore.3 |   28 ++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+)
 create mode 100644 doc/gencore.1
 create mode 100644 doc/gencore.3

diff --git a/doc/gencore.1 b/doc/gencore.1
new file mode 100644
index 0000000..3a7eb8f
--- /dev/null
+++ b/doc/gencore.1
@@ -0,0 +1,31 @@
+.\" Manpage for gencore.
+.\" Contact jananive@linux.vnet.ibm.in to correct errors or typos.
+.TH man 2 "11 Dec 2013" "1.0" "gencore man page"
+.SH NAME
+gencore \- generates coredump
+.SH SYNOPSIS
+gencore pid [output-file-name]
+.SH DESCRIPTION
+gencore takes a dump of the process whose PID is passed
+as a command line argument. If the output file name is
+specified,the core is dumped in that name, if not the
+default filename is core.pid.
+If through options we specify --daemon, in this case the
+gencore command helps in performing a selfdump.Any process
+can connect to this daemon created and request for a dump.
+
+.SH OPTIONS
+--daemon   Creates a daemon to perform selfdumps
+
+--socket   Performs selfdumps with systemd taking care of socket connections.
+	   For this we need to have the correct version of systemd which
+	   has this socket option enabled.
+
+.SH SEE ALSO
+ptrace(2), process_vm_readv(2), gencore(3)
+.SH BUGS
+No known bugs.
+.SH AUTHOR
+Janani Venkataraman <jananive@linux.vnet.ibm.com>
+
+Suzuki Poulose <suzuki@linux.vnet.ibm.com>
diff --git a/doc/gencore.3 b/doc/gencore.3
new file mode 100644
index 0000000..bc77b10
--- /dev/null
+++ b/doc/gencore.3
@@ -0,0 +1,28 @@
+.\" Manpage for libgencore.
+.\" Contact jananive@linux.vnet.ibm.in to correct errors or typos.
+.TH man 3 "11 Dec 2013" "1.0" "libgencore man page"
+.SH NAME
+gencore \- generates coredump
+.SH SYNOPSIS
+int gencore(char *corefile);
+.SH DESCRIPTION
+gencore takes a dump of the process who sends a message
+to the already running gencore daemon asking for a dump.
+The client or the requester specifies the corefile name
+and the dump is generated in the path specified. This name
+can be a relative or an absolute path.
+.SH RETURN VALUE
+gencore returns 0 on success and the appropriate error
+number on a failure.
+.SH ERRORS
+gencore() may fail and returns the errors for the individual operations
+performed by the daemon or server during the coredump generation.
+.SH OPTIONS
+.SH SEE ALSO
+ptrace(2), process_vm_readv(2), socket(2), listen(2), chmod(2),
+getsockopt(2), setuid(2), setgid(2), geteuid(2), daemon(3),
+bind(2), accept(2).
+.SH BUGS
+No known bugs.
+.SH AUTHOR
+Janani Venkataraman <jananive@linux.vnet.ibm.com>


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 29/33] Automake files for the doc folder
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (27 preceding siblings ...)
  2014-03-20  9:43 ` [PATCH 28/33] Man pages Janani Venkataraman
@ 2014-03-20  9:43 ` Janani Venkataraman
  2014-03-20  9:43 ` [PATCH 30/33] README, COPYING, Changelog Janani Venkataraman
                   ` (5 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Automake files for both gencore command and gencore API.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 Makefile.am     |    2 +-
 configure.ac    |    2 +-
 doc/Makefile.am |    2 ++
 src/coredump.c  |    0 
 4 files changed, 4 insertions(+), 2 deletions(-)
 create mode 100644 doc/Makefile.am
 mode change 100755 => 100644 src/coredump.c

diff --git a/Makefile.am b/Makefile.am
index dfa49b2..8b31e4f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,2 +1,2 @@
 AUTOMAKE_OPTIONS = foreign
-SUBDIRS = src
+SUBDIRS = src doc
diff --git a/configure.ac b/configure.ac
index 8c785cd..9e130e0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,4 +4,4 @@ AM_INIT_AUTOMAKE([-Wall -Werror foreign])
 AC_CONFIG_HEADERS([config.h])
 AC_PROG_CC
 AC_CONFIG_FILES(Makefile)
-AC_OUTPUT(src/Makefile)
+AC_OUTPUT(src/Makefile doc/Makefile)
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..a1cf9b5
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,2 @@
+man1_MANS = gencore.1
+man3_MANS = gencore.3
diff --git a/src/coredump.c b/src/coredump.c
old mode 100755
new mode 100644


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 30/33] README, COPYING, Changelog
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (28 preceding siblings ...)
  2014-03-20  9:43 ` [PATCH 29/33] Automake files for the doc folder Janani Venkataraman
@ 2014-03-20  9:43 ` Janani Venkataraman
  2014-03-20  9:43 ` [PATCH 31/33] Spec file Janani Venkataraman
                   ` (4 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Adding the README, COPYING and ChangeLog for the package.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 COPYING            |   24 ++++++++++++
 COPYING.LIBGENCORE |   24 ++++++++++++
 Changelog          |    7 +++
 README             |  108 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 163 insertions(+)
 create mode 100644 COPYING
 create mode 100644 COPYING.LIBGENCORE
 create mode 100644 Changelog
 create mode 100644 README

diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..a4163ed
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,24 @@
+-------
+GENCORE
+-------
+
+Gencore produces a coredump of a process non-disruptively
+
+Copyright (C) IBM Corporation, 2013 
+
+Authors:
+	Janani Venkataraman <jananive@in.ibm.com>
+
+This package is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This package is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software Foundation,
+Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
diff --git a/COPYING.LIBGENCORE b/COPYING.LIBGENCORE
new file mode 100644
index 0000000..e1a7bf6
--- /dev/null
+++ b/COPYING.LIBGENCORE
@@ -0,0 +1,24 @@
+----------
+LIBGENCORE
+----------
+
+Libencore sets up the interface for requesting a selfdump.
+
+Copyright (C) IBM Corporation, 2013 
+
+Authors:
+	Janani Venkataraman <jananive@in.ibm.com>
+
+This package is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This package is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software Foundation,
+Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
diff --git a/Changelog b/Changelog
new file mode 100644
index 0000000..0c780ca
--- /dev/null
+++ b/Changelog
@@ -0,0 +1,7 @@
+---------
+Changelog
+---------
+
+* Thursday Dec 19 2013 Janani Venkataraman <jananive@linux.vnet.ibm.com> 1.0
+
+- Initial Version
diff --git a/README b/README
new file mode 100644
index 0000000..2935ddb
--- /dev/null
+++ b/README
@@ -0,0 +1,108 @@
+-----------------------------------------------
+How to build and install the package -- src.rpm
+-----------------------------------------------
+
+a) Download the gencore-0.1-0.src.rpm
+b) Rebuild the src.rpm using the following command:
+	rpmbuild --rebuild gencore-0.1-0.src.rpm
+c) In the rpmbuild folder created install the RPMs in RPMS folder
+   through the following command:
+	rpm -ivh gencore-0.1-0.x86_64.rpm gencore-debuginfo-0.1-0.x86_64.rpm libgencore-0.1-0.x86_64.rpm libgencore-devel-0.1-0.x86_64.rpm
+c) The library and executables will be installed in /usr/bin
+   and /usr/lib64 and the daemon will be started automatically.
+
+----------------------------------------------
+How to build and install the package -- tar.gz
+----------------------------------------------
+
+a) Untar it firstly
+b) ./autoreconf --force --install
+c) ./configure --prefix="path"
+d) make
+e) make install
+
+The executable the the client libraries are installed in the path specified by
+the user.
+
+--------------------------------
+Command Line Arguments - gencore
+--------------------------------
+
+We can call the gencore command in two ways.
+a) gencore pid [output-file-name]
+b) gencore --daemon 
+   -- Creates a daemon, for aiding selfdumps.
+c) gencore --socket
+   -- Post installation, systemd will create the socket and listen for connections.
+      Once a process requests a selfdump, the service will be spawned to handle
+      the request. For this we need to have the correct version of systemd which
+      has this socket option enabled.
+
+In the first case, gencore performs a third party dump and we can specify the
+PID of the process to be dumped. The output-filename is optional. If not 
+specified, by default the core filename is core.pid and it is created in the CWD.
+
+In the second case, we start a daemon and we wait for requests from processes
+which requires a self dump. This daemon keeping waiting for such requests.
+It can handle multiple requests for the dump. This method was adapted from the
+CRIU self dump application.
+
+A process which wants a dump, uses the libgencore library and calls the function
+gencore(char *corefile).
+
+----------------------------------
+libgencore - gencore() -- selfdump
+----------------------------------
+
+A program can request a dump of itself. Such a dump is known as a self dump.
+This can be done by using the library libgencore and calling the function
+gencore(char *corefile).
+
+For a selfdump, we need to first start gencore --daemon like mentioned before.
+This daemon waits for requests for dumps. This is already done post installation.
+
+Then in the process, which requests for a dump, we need to call the function 
+gencore(char *absolute/relative pathname);
+
+We use libgencore library to set up this interface.
+
+eg. test.c
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+int (*gencore)(char *name);
+
+void segv_handler(int signo)
+{
+	int ret;
+
+	ret = gencore("/home/janani/demo/test_core");
+
+	fprintf(stderr, "Status of dump: %s\n", strerror(ret)); 	
+}
+	
+int main ()
+{
+	void *lib;
+
+	signal(SIGSEGV, segv_handler);
+	
+	/* Opening the library, in this case the library is present in the /usr/lib64 */
+	lib = dlopen("libgencore.so", RTLD_LAZY);
+
+	gencore = dlsym(lib, "gencore");
+
+	sleep(100);
+
+	return 0;
+}
+
+-------
+AUTHORS
+-------
+
+Janani Venkataraman <jananive@in.ibm.com>
+


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 31/33] Spec file
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (29 preceding siblings ...)
  2014-03-20  9:43 ` [PATCH 30/33] README, COPYING, Changelog Janani Venkataraman
@ 2014-03-20  9:43 ` Janani Venkataraman
  2014-03-20  9:43 ` [PATCH 32/33] Socket and Service files Janani Venkataraman
                   ` (3 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

Adding the Spec file for the package

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 Makefile.am      |    5 ++++
 configure.ac     |    2 +-
 gencore.spec.in  |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 libgencore.pc.in |    8 ++++++
 4 files changed, 81 insertions(+), 1 deletion(-)
 create mode 100644 gencore.spec.in
 create mode 100644 libgencore.pc.in

diff --git a/Makefile.am b/Makefile.am
index 8b31e4f..30e86f5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,2 +1,7 @@
 AUTOMAKE_OPTIONS = foreign
 SUBDIRS = src doc
+
+EXTRA_DIST = src/coredump.h src/elf.c src/elf-compat.h doc/gencore.1 doc/gencore.3 Changelog COPYING.LIBGENCORE
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libgencore.pc
diff --git a/configure.ac b/configure.ac
index 9e130e0..6245ae1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,5 +3,5 @@ LT_INIT()
 AM_INIT_AUTOMAKE([-Wall -Werror foreign])
 AC_CONFIG_HEADERS([config.h])
 AC_PROG_CC
-AC_CONFIG_FILES(Makefile)
+AC_CONFIG_FILES(Makefile gencore.spec libgencore.pc)
 AC_OUTPUT(src/Makefile doc/Makefile)
diff --git a/gencore.spec.in b/gencore.spec.in
new file mode 100644
index 0000000..58c699e
--- /dev/null
+++ b/gencore.spec.in
@@ -0,0 +1,67 @@
+Name: gencore
+Version: @VERSION@
+Release: 0
+License: GPLv2
+Group: Applications/System
+Source: %{name}-%{version}.tar.gz
+Summary: Tool for capturing application core dump non-disruptively.
+
+%package -n libgencore
+Group: System Environment/Libraries
+Summary: Library interface for generating non-disruptive core dump.
+Requires: gencore == %{version}
+ 
+%package -n libgencore-devel
+Group: Development/Libraries
+Summary: libgencore development files
+
+%description
+This package, helps in taking non-disruptive coredumps of a process,
+when requested for. When the PID of a process is passed to this command,
+this command takes a dump of that process and stores the dump in the
+filename specified or by default core.pid in the current working directory.
+
+%description -n libgencore
+The library libgencore, sets up the interface for such dump
+requests and provides an API for initiating a dump of the running
+program via gencore daemon.
+
+%description -n libgencore-devel
+This package contains necessary header files for libgencore.
+
+%prep
+%setup
+
+%build
+%configure
+make
+
+%install
+make DESTDIR=$RPM_BUILD_ROOT install
+
+%files
+%doc README COPYING Changelog
+%{_bindir}/gencore
+%{_mandir}/man1/gencore.1*
+
+%files -n libgencore
+%doc COPYING.LIBGENCORE
+%{_libdir}/libgencore.so.*
+%{_mandir}/man3/gencore.3*
+
+%files -n libgencore-devel
+%{_includedir}/gencore.h
+%{_libdir}/libgencore.so
+%{_libdir}/libgencore.a
+%{_libdir}/libgencore.la
+%{_libdir}/pkgconfig/libgencore.pc
+
+%post -n libgencore
+ldconfig -n %{_libdir}/libgencore.so.*
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%changelog
+* Mon Dec 23 2013  - Janani Venkataraman <jananive@linux.vnet.ibm.com>
+- Initial Version
diff --git a/libgencore.pc.in b/libgencore.pc.in
new file mode 100644
index 0000000..b24dc0e
--- /dev/null
+++ b/libgencore.pc.in
@@ -0,0 +1,8 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libgencore
+Libs:-L${libdir} -lgencore
+Cflags: -I${includedir}


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 32/33] Socket and Service files.
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (30 preceding siblings ...)
  2014-03-20  9:43 ` [PATCH 31/33] Spec file Janani Venkataraman
@ 2014-03-20  9:43 ` Janani Venkataraman
  2014-03-20  9:44 ` [PATCH 33/33] Support check Janani Venkataraman
                   ` (2 subsequent siblings)
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

The socket and service files for systemd are created.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 Makefile.am      |   15 +++++++++++++++
 configure.ac     |    1 +
 gencore.service  |    9 +++++++++
 gencore.socket   |   10 ++++++++++
 gencore.spec.in  |   21 +++++++++++++++++++++
 gencore@.service |    9 +++++++++
 6 files changed, 65 insertions(+)
 create mode 100644 gencore.service
 create mode 100644 gencore.socket
 create mode 100644 gencore@.service

diff --git a/Makefile.am b/Makefile.am
index 30e86f5..4c6c269 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,5 +3,20 @@ SUBDIRS = src doc
 
 EXTRA_DIST = src/coredump.h src/elf.c src/elf-compat.h doc/gencore.1 doc/gencore.3 Changelog COPYING.LIBGENCORE
 
+if HAVE_SYSTEMD_SOCKET_SUPPORT 
+EXTRA_DIST += gencore.socket gencore@.service
+else
+EXTRA_DIST += gencore.service
+endif
+
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libgencore.pc
+
+systemddir = /usr/lib/systemd
+systemdir = /usr/lib/systemd/system
+
+if HAVE_SYSTEMD_SOCKET_SUPPORT
+system_DATA = gencore@.service gencore.socket
+else
+system_DATA = gencore.service
+endif
diff --git a/configure.ac b/configure.ac
index 6245ae1..39d7902 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,4 +4,5 @@ AM_INIT_AUTOMAKE([-Wall -Werror foreign])
 AC_CONFIG_HEADERS([config.h])
 AC_PROG_CC
 AC_CONFIG_FILES(Makefile gencore.spec libgencore.pc)
+AM_CONDITIONAL(HAVE_SYSTEMD_SOCKET_SUPPORT, test "have_systemd_socket_support" = false)
 AC_OUTPUT(src/Makefile doc/Makefile)
diff --git a/gencore.service b/gencore.service
new file mode 100644
index 0000000..79220ff
--- /dev/null
+++ b/gencore.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Gencore service
+
+[Service]
+Type=forking
+ExecStart=/usr/bin/gencore --daemon
+
+[Install]
+WantedBy=multi-user.target
diff --git a/gencore.socket b/gencore.socket
new file mode 100644
index 0000000..b9afce8
--- /dev/null
+++ b/gencore.socket
@@ -0,0 +1,10 @@
+[Unit]
+Description=Gencore socket
+
+[Socket]
+ListenStream=/var/run/gencored.socket
+Accept=true
+
+[Install]
+WantedBy=socket.target
+
diff --git a/gencore.spec.in b/gencore.spec.in
index 58c699e..3937edb 100644
--- a/gencore.spec.in
+++ b/gencore.spec.in
@@ -1,3 +1,5 @@
+%define HAVE_SYSTEMD_SOCKET_SUPPORT 0
+
 Name: gencore
 Version: @VERSION@
 Release: 0
@@ -39,10 +41,19 @@ make
 %install
 make DESTDIR=$RPM_BUILD_ROOT install
 
+%preun
+systemctl stop gencore.service
+
 %files
 %doc README COPYING Changelog
 %{_bindir}/gencore
 %{_mandir}/man1/gencore.1*
+%if %HAVE_SYSTEMD_SOCKET_SUPPORT
+%{_unitdir}/gencore@.service
+%{_unitdir}/gencore.socket
+%else
+%{_unitdir}/gencore.service
+%endif
 
 %files -n libgencore
 %doc COPYING.LIBGENCORE
@@ -56,6 +67,16 @@ make DESTDIR=$RPM_BUILD_ROOT install
 %{_libdir}/libgencore.la
 %{_libdir}/pkgconfig/libgencore.pc
 
+%post
+systemctl --system daemon-reload
+%if %HAVE_SYSTEMD_SOCKET_SUPPORT
+systemctl enable gencore.socket
+systemctl start gencore.socket 
+%else
+systemctl enable gencore.service
+systemctl start gencore.service 
+%endif
+
 %post -n libgencore
 ldconfig -n %{_libdir}/libgencore.so.*
 
diff --git a/gencore@.service b/gencore@.service
new file mode 100644
index 0000000..4dcfb1c
--- /dev/null
+++ b/gencore@.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Gencore service
+
+[Service]
+Type=forking
+ExecStart=/usr/bin/gencore --socket
+
+[Install]
+WantedBy=multi-user.target


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 33/33] Support check
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (31 preceding siblings ...)
  2014-03-20  9:43 ` [PATCH 32/33] Socket and Service files Janani Venkataraman
@ 2014-03-20  9:44 ` Janani Venkataraman
  2014-03-20 10:24 ` [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Pádraig Brady
  2014-03-21  8:17 ` Karel Zak
  34 siblings, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-20  9:44 UTC (permalink / raw)
  To: linux-kernel
  Cc: amwang, procps, rdunlap, james.hogan, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

This checks if a particular build can support dumps on 32/64 bit applications.

For eg. A 32bit build of gencore cant support dumps on 64 bit applications.

Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
---
 src/coredump.c |   11 +++++++++++
 src/elf64.c    |    2 ++
 2 files changed, 13 insertions(+)

diff --git a/src/coredump.c b/src/coredump.c
index 98a7146..49af7b3 100644
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -76,6 +76,17 @@ struct core_proc cp;
 /* PID of Daemon */
 int pid_log;
 
+/* Support Check */
+static int support_check(int pid, struct core_proc *cp)
+{
+	gencore_log("This build of gencore(32bit) cannot dump a 64bit process.\n");
+	return -1;
+}
+
+#if defined(__i386) || (defined(__s390__) && !defined(__s390x__)) || (defined(__PPC__) && !defined(__PPC64__))
+#define do_elf64_coredump support_check
+#endif
+
 /* Initialised core process members */
 void init_core(void)
 {
diff --git a/src/elf64.c b/src/elf64.c
index 651f218..11c8c76 100644
--- a/src/elf64.c
+++ b/src/elf64.c
@@ -28,6 +28,7 @@
  * and operations once elf.c is included.
  */
 
+#if defined(__x86_64) || (defined(__s390x__) && defined(__s390__)) || (defined(__PPC64__) && defined(__PPC__))
 #define do_elf_coredump do_elf64_coredump
 
 #define Elf_Ehdr Elf64_Ehdr
@@ -40,3 +41,4 @@
 #define Elf_Addr Elf64_Addr
 
 #include "elf.c"
+#endif


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (32 preceding siblings ...)
  2014-03-20  9:44 ` [PATCH 33/33] Support check Janani Venkataraman
@ 2014-03-20 10:24 ` Pádraig Brady
  2014-03-21  8:17 ` Karel Zak
  34 siblings, 0 replies; 44+ messages in thread
From: Pádraig Brady @ 2014-03-20 10:24 UTC (permalink / raw)
  To: Janani Venkataraman
  Cc: linux-kernel, amwang, procps, rdunlap, james.hogan, aravinda,
	hch, jeremy.fitzhardinge, xemul, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

On 03/20/2014 09:39 AM, Janani Venkataraman wrote:
> Hi all,
> 
> The following series implements an infrastructure for capturing the core of an
> application without disrupting its process.
> 
> Kernel Space Approach:
> 
> 1) Posted an RFD to LKML explaining the various kernel-methods being analysed.
> 
> https://lkml.org/lkml/2013/9/3/122
> 
> 2) Went ahead to implement the same using the task_work_add approach and posted an
> RFC to LKML.
> 
> http://lwn.net/Articles/569534/
> 
> Based on the responses, the present approach implements the same in User-Space.
> 
> User Space Approach:
> 
> We didn't adopt the CRIU approach because our method would give us a head
> start, as all that the distro would need is the PTRACE_functionality and nothing
> more which is available from kernel versions 3.4 and above.
> 
> Basic Idea of User Space:
> 
> 1) The threads are held using PTRACE_SEIZE and PTRACE_INTERRUPT.
> 
> 2) The dump is then taken using the following:
>     1) The register sets namely general purpose, floating point and the arch
>     specific register sets are collected through PTRACE_GETREGSET calls by
>     passing the appropriate register type as parameter.
>     2) The virtual memory maps are collected from /proc/pid/maps.
>     3) The auxiliary vector is collected from /proc/pid/auxv.
>     4) Process state information for filling the notes such as PRSTATUS and
>     PRPSINFO are collected from /proc/pid/stat and /proc/pid/status.
>     5) The actual memory is read through process_vm_readv syscall as suggested
>     by Andi Kleen.
>     6) Command line arguments are collected from /proc/pid/cmdline
> 
> 3) The threads are then released using PTRACE_DETACH.
> 
> Self Dump:
> 
> A self dump is implemented with the following approach which was adapted
> from CRIU:
> 
> Gencore Daemon
> 
> The programs can request a dump using gencore() API, provided through
> libgencore. This is implemented through a daemon which listens on a UNIX File
> socket. The daemon is started immediately post installation.
> 
> We have provided service scripts for integration with systemd.
> 
> NOTE:
> 
> On systems with systemd, we could make use of socket option, which will avoid
> the need for running the gencore daemon always. The systemd can wait on the
> socket for requests and trigger the daemon as and when required. However, since
> the systemd socket APIs are not exported yet, we have disabled the supporting
> code for this feature.
> 
> libgencore:
> 
> 1) The client interface is a standard library call. All that the dump requester
> does is open the library and call the gencore() API and the dump will be
> generated in the path specified(relative/absolute).
> 
> To Do:
> 
> 1) Presently we wait indefinitely for the all the threads to seize. We can add
> a time-out to decide how much time we need to wait for the threads to be
> seized. This can be passed as command line argument in the case of a third
> party dump and in the case of the self-dump through the library call. We need
> to work on how much time to wait.
> 
> 2) Like mentioned before, the systemd socket APIs are not exported yet and
> hence this option is disabled now. Once these API's are available we can enable
> the socket option.
> 
> We would like to push this to one of the following packages:
> a) util-linux
> b) coreutils
> c) procps-ng
> 
> We are not sure which one would suit this application the best.
> Please let us know your views on the same.

Well from coreutils persepective, they're generally
non Linux specific _commands_, and so wouldn't be
a natural home for this (despite the _core_ in the name :)).

thanks,
Pádraig.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 04/33] Hold threads
  2014-03-20  9:39 ` [PATCH 04/33] Hold threads Janani Venkataraman
@ 2014-03-20 19:01   ` Pavel Emelyanov
  2014-03-25  6:58     ` Janani Venkataraman
  2014-04-18 14:04     ` Janani Venkataraman
  0 siblings, 2 replies; 44+ messages in thread
From: Pavel Emelyanov @ 2014-03-20 19:01 UTC (permalink / raw)
  To: Janani Venkataraman
  Cc: linux-kernel, amwang, procps, rdunlap, james.hogan, aravinda,
	hch, mhiramat, jeremy.fitzhardinge, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds

On 03/20/2014 01:39 PM, Janani Venkataraman wrote:
> Getting number of threads and their respective IDs through /proc/pid/stat and
> /proc/pid/task.
> 
> The threads are then seized and interrupted. After the dump is taken they are
> detached.
> 
> Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
> ---

> +/* Gets the Thread IDS and siezes them */
> +int seize_threads(int pid)
> +{
> +	char filename[40];
> +	DIR *dir;
> +	int ct = 0, ret = 0, tmp_tid;
> +	struct dirent *entry;
> +	char state;
> +
> +	ret = get_thread_count(pid);
> +	if (ret == -1)
> +		return -1;
> +
> +	cp.thread_count = ret;
> +	cp.t_id = calloc(cp.thread_count, sizeof(int));
> +	if (!cp.t_id) {
> +		status = errno;
> +		gencore_log("Could not allocate memory for thread_ids.\n");
> +		return -1;
> +	}
> +
> +	snprintf(filename, 40, "/proc/%d/task", pid);
> +	dir = opendir(filename);
> +
> +	while ((entry = readdir(dir))) {

This simple loop is not enough -- threads may appear and disappear while
you do the readdir and seize, so you should scan it several times to
make sure you caught all the threads.

You can look at how this is done in CRIU in cr-dump,c:collect_threads().

> +		if (entry->d_type == DT_DIR && entry->d_name[0] != '.') {
> +			tmp_tid = atoi(entry->d_name);
> +			ret = ptrace(PTRACE_SEIZE, tmp_tid, 0, 0);
> +			if (ret) {
> +				state = get_thread_status(tmp_tid);
> +				if (state == 'Z')
> +					goto assign;
> +				status = errno;
> +				gencore_log("Could not seize thread: %d\n",
> +								tmp_tid);
> +				break;
> +			}
> +			ret = ptrace(PTRACE_INTERRUPT, tmp_tid, 0, 0);
> +			if (ret) {
> +				state = get_thread_status(tmp_tid);
> +				if (state == 'Z')
> +					goto assign;
> +				status = errno;
> +				gencore_log("Could not interrupt thread: %d\n",
> +								tmp_tid);
> +				break;
> +			}
> +assign:
> +			/* If a new thread, is created after we fetch the thread_count,
> +			 * we may encounter a buffer overflow situation in the cp_tid.
> +			 * Hence we check this case and re-allocate memory if required.
> +			 */
> +			cp.t_id[ct++] = tmp_tid;
> +		}
> +	}
> +
> +	/* Reassigning based on successful seizes */
> +	cp.thread_count = ct;
> +
> +	closedir(dir);
> +
> +	/* Successful seize and interrupt on all threads makes ret = 0 */
> +	return ret;
> +}

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure
  2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
                   ` (33 preceding siblings ...)
  2014-03-20 10:24 ` [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Pádraig Brady
@ 2014-03-21  8:17 ` Karel Zak
  2014-03-21 15:02   ` Phillip Susi
  2014-03-24  9:38   ` Janani Venkataraman
  34 siblings, 2 replies; 44+ messages in thread
From: Karel Zak @ 2014-03-21  8:17 UTC (permalink / raw)
  To: Janani Venkataraman; +Cc: linux-kernel, util-linux

On Thu, Mar 20, 2014 at 03:09:03PM +0530, Janani Venkataraman wrote:
> Gencore Daemon
> 
> The programs can request a dump using gencore() API, provided through
> libgencore. This is implemented through a daemon which listens on a UNIX File
> socket. The daemon is started immediately post installation.

 The gencore command looks like a good idea, but why we need the
 client-server infrastructure? At least at first glance it seems
 like overkill.

> We would like to push this to one of the following packages:
> a) util-linux
> b) coreutils
> c) procps-ng

  d) somewhere near to gdb :-)

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure
  2014-03-21  8:17 ` Karel Zak
@ 2014-03-21 15:02   ` Phillip Susi
  2014-03-24  9:43     ` Janani Venkataraman
  2014-03-24  9:38   ` Janani Venkataraman
  1 sibling, 1 reply; 44+ messages in thread
From: Phillip Susi @ 2014-03-21 15:02 UTC (permalink / raw)
  To: Karel Zak, Janani Venkataraman; +Cc: linux-kernel, util-linux

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 3/21/2014 4:17 AM, Karel Zak wrote:
> The gencore command looks like a good idea, but why we need the 
> client-server infrastructure? At least at first glance it seems 
> like overkill.

Yes, the server seems pointless.

>> We would like to push this to one of the following packages: a)
>> util-linux b) coreutils c) procps-ng
> 
> d) somewhere near to gdb :-)

gdb already has such a thing; it's called gcore.  Kind of makes this
work seem redundant?


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.17 (MingW32)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQEcBAEBAgAGBQJTLFSjAAoJEI5FoCIzSKrwuTIH/jGtc3dB1WKgtDSE2wtXXHO0
0WxhWDbVkpJ0Q+tkG/tjw4wudYtEJ+XAHsCIK3vH7OMX7i4PMOLDgjT/FyxTPrWl
W+eUCazi4vRPNGscii5mRFlsthgEd2pofotlx5UB7Br9D05/QZqErtEMJMqD935V
94wlvJSvJI0n3hfAUgcM8apxTgxYr/TIPEQPfqLem3xTZIw3lTRic613Qji2Kwif
l+kqs0WLy/AHEwBLRrXDQahnv5n2IhOVUn3KDwm9Su56rbrmAF7LAvK0+uxRyoQk
IVC5h8BdBQ4QMYl7KYYEPy+n+0Qbe1EQ4tLmYvaEBwXP5c0QDGX0M5VUkko+eGI=
=zFoW
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure
  2014-03-21  8:17 ` Karel Zak
  2014-03-21 15:02   ` Phillip Susi
@ 2014-03-24  9:38   ` Janani Venkataraman
  1 sibling, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-24  9:38 UTC (permalink / raw)
  To: Karel Zak
  Cc: linux-kernel, amwang, rdunlap, andi, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, suzuki, kosaki.motohiro, adobriyan,
	tarundsk, vapier, roland, tj, ananth, gorcunov, avagin, oleg,
	eparis, d.hatayama, james.hogan, akpm, torvalds, coreutils,
	procps, util-linux


On 03/21/2014 01:47 PM, Karel Zak wrote:
> On Thu, Mar 20, 2014 at 03:09:03PM +0530, Janani Venkataraman wrote:
>> Gencore Daemon
>>
>> The programs can request a dump using gencore() API, provided through
>> libgencore. This is implemented through a daemon which listens on a UNIX File
>> socket. The daemon is started immediately post installation.
>   The gencore command looks like a good idea, but why we need the
>   client-server infrastructure? At least at first glance it seems
>   like overkill.
We are also looking at a process being able to do a self dump. ptrace 
SEIZE/INTERRUPT
cannot be used on one-self and hencewe need to offload the dump another 
'process'.
Since we can't fork(), as it is not signal safe, we need a dedicated 
process to handle
such requests. Hence the server.

https://lkml.org/lkml/2013/9/3/122


>> We would like to push this to one of the following packages:
>> a) util-linux
>> b) coreutils
>> c) procps-ng
>    d) somewhere near to gdb :-)
>
>      Karel
>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure
  2014-03-21 15:02   ` Phillip Susi
@ 2014-03-24  9:43     ` Janani Venkataraman
  2014-03-24 13:54       ` Phillip Susi
  0 siblings, 1 reply; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-24  9:43 UTC (permalink / raw)
  To: Phillip Susi, Karel Zak
  Cc: amwang, rdunlap, andi, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, suzuki, kosaki.motohiro, adobriyan,
	tarundsk, vapier, roland, tj, ananth, gorcunov, avagin, oleg,
	eparis, d.hatayama, james.hogan, akpm, torvalds, coreutils,
	procps, util-linux, util-linux, linux-kernel


On 03/21/2014 08:32 PM, Phillip Susi wrote:
> On 3/21/2014 4:17 AM, Karel Zak wrote:
>> The gencore command looks like a good idea, but why we need the
>> client-server infrastructure? At least at first glance it seems
>> like overkill.
> Yes, the server seems pointless.
>
>>> We would like to push this to one of the following packages: a)
>>> util-linux b) coreutils c) procps-ng
>> d) somewhere near to gdb :-)
> gdb already has such a thing; it's called gcore.  Kind of makes this
> work seem redundant?

Gcore attaches to the process using gdb and runs the gdb gcore command
and then detaches. In gcore the dump cannot be issued from a signal handler
context as fork() is not signal safe and moreover it is disruptive in nature as the
gdb attaches using ptrace which sends a SIGSTOP signal. Hence the gcore method
cannot be used if the process wants to initiate a self dump as well.
The following link points to a discussion regarding why not gcore.

https://lkml.org/lkml/2013/9/3/122

>


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure
  2014-03-24  9:43     ` Janani Venkataraman
@ 2014-03-24 13:54       ` Phillip Susi
  2014-07-03 12:59         ` Suzuki K. Poulose
  0 siblings, 1 reply; 44+ messages in thread
From: Phillip Susi @ 2014-03-24 13:54 UTC (permalink / raw)
  To: Janani Venkataraman, Karel Zak
  Cc: amwang, rdunlap, andi, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, suzuki, kosaki.motohiro, adobriyan,
	tarundsk, vapier, roland, tj, ananth, gorcunov, avagin, oleg,
	eparis, d.hatayama, james.hogan, akpm, torvalds, coreutils,
	procps, util-linux, linux-kernel

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 3/24/2014 5:43 AM, Janani Venkataraman wrote:
> Gcore attaches to the process using gdb and runs the gdb gcore
> command and then detaches. In gcore the dump cannot be issued from
> a signal handler context as fork() is not signal safe and moreover
> it is disruptive in

You can fork+exec from a signal handler just fine.


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.17 (MingW32)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQEcBAEBAgAGBQJTMDknAAoJEI5FoCIzSKrwo2QH/RCmAn404PlO6cZLNuQ5PXqc
MdR6U62K/BwZo42Fr694FzzjGKwuqx3YHB8gU+tyE26yZ31reFWG8KpdfV46NRYG
sEPH/lJOerMXwfbpxE0YFZBow5wZqTg/XsiXMyz8M4/KdMgOgCEqsaG/IRPvK0+B
NiaQmFct0Y2onwoy50mrR2sGeKOgA5510osoChCq+TKUrsCJp80jYvz6bVOi6kwY
Oi+bAl/tzcQDy7yHkUqYJXYRf3o9jbHqGxnC/IzygOntggqmIiB8ez4ZDZC2YbOl
htv0gP/jqZk8Pm3C/gv5S7xhqjy2+yvkWXg7mhsz7gsbSA4K5LXd5bN5ovEBGAw=
=JWwx
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 04/33] Hold threads
  2014-03-20 19:01   ` Pavel Emelyanov
@ 2014-03-25  6:58     ` Janani Venkataraman
  2014-04-18 14:04     ` Janani Venkataraman
  1 sibling, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-03-25  6:58 UTC (permalink / raw)
  To: Pavel Emelyanov
  Cc: linux-kernel, amwang, procps, rdunlap, james.hogan, aravinda,
	hch, mhiramat, jeremy.fitzhardinge, d.hatayama, coreutils,
	kosaki.motohiro, adobriyan, util-linux, tarundsk, vapier, roland,
	ananth, gorcunov, avagin, oleg, eparis, suzuki, andi, tj, akpm,
	torvalds


On 03/21/2014 12:31 AM, Pavel Emelyanov wrote:
> On 03/20/2014 01:39 PM, Janani Venkataraman wrote:
>> Getting number of threads and their respective IDs through /proc/pid/stat and
>> /proc/pid/task.
>>
>> The threads are then seized and interrupted. After the dump is taken they are
>> detached.
>>
>> Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
>> ---
>> +/* Gets the Thread IDS and siezes them */
>> +int seize_threads(int pid)
>> +{
>> +	char filename[40];
>> +	DIR *dir;
>> +	int ct = 0, ret = 0, tmp_tid;
>> +	struct dirent *entry;
>> +	char state;
>> +
>> +	ret = get_thread_count(pid);
>> +	if (ret == -1)
>> +		return -1;
>> +
>> +	cp.thread_count = ret;
>> +	cp.t_id = calloc(cp.thread_count, sizeof(int));
>> +	if (!cp.t_id) {
>> +		status = errno;
>> +		gencore_log("Could not allocate memory for thread_ids.\n");
>> +		return -1;
>> +	}
>> +
>> +	snprintf(filename, 40, "/proc/%d/task", pid);
>> +	dir = opendir(filename);
>> +
>> +	while ((entry = readdir(dir))) {
> This simple loop is not enough -- threads may appear and disappear while
> you do the readdir and seize, so you should scan it several times to
> make sure you caught all the threads.
I will look into this.
> You can look at how this is done in CRIU in cr-dump,c:collect_threads().
Yes I will look into that function. Thanks.

Thanks.
Janani
>> +		if (entry->d_type == DT_DIR && entry->d_name[0] != '.') {
>> +			tmp_tid = atoi(entry->d_name);
>> +			ret = ptrace(PTRACE_SEIZE, tmp_tid, 0, 0);
>> +			if (ret) {
>> +				state = get_thread_status(tmp_tid);
>> +				if (state == 'Z')
>> +					goto assign;
>> +				status = errno;
>> +				gencore_log("Could not seize thread: %d\n",
>> +								tmp_tid);
>> +				break;
>> +			}
>> +			ret = ptrace(PTRACE_INTERRUPT, tmp_tid, 0, 0);
>> +			if (ret) {
>> +				state = get_thread_status(tmp_tid);
>> +				if (state == 'Z')
>> +					goto assign;
>> +				status = errno;
>> +				gencore_log("Could not interrupt thread: %d\n",
>> +								tmp_tid);
>> +				break;
>> +			}
>> +assign:
>> +			/* If a new thread, is created after we fetch the thread_count,
>> +			 * we may encounter a buffer overflow situation in the cp_tid.
>> +			 * Hence we check this case and re-allocate memory if required.
>> +			 */
>> +			cp.t_id[ct++] = tmp_tid;
>> +		}
>> +	}
>> +
>> +	/* Reassigning based on successful seizes */
>> +	cp.thread_count = ct;
>> +
>> +	closedir(dir);
>> +
>> +	/* Successful seize and interrupt on all threads makes ret = 0 */
>> +	return ret;
>> +}


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 04/33] Hold threads
  2014-03-20 19:01   ` Pavel Emelyanov
  2014-03-25  6:58     ` Janani Venkataraman
@ 2014-04-18 14:04     ` Janani Venkataraman
  1 sibling, 0 replies; 44+ messages in thread
From: Janani Venkataraman @ 2014-04-18 14:04 UTC (permalink / raw)
  To: Pavel Emelyanov
  Cc: amwang, procps, oleg, rdunlap, tarundsk, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, suzuki, coreutils, kosaki.motohiro,
	adobriyan, util-linux, james.hogan, roland, ananth, gorcunov,
	avagin, linux-kernel, eparis, d.hatayama, andi, tj, akpm,
	torvalds

[-- Attachment #1: Type: text/plain, Size: 6087 bytes --]


On 03/21/2014 12:31 AM, Pavel Emelyanov wrote:
> On 03/20/2014 01:39 PM, Janani Venkataraman wrote:
>> Getting number of threads and their respective IDs through /proc/pid/stat and
>> /proc/pid/task.
>>
>> The threads are then seized and interrupted. After the dump is taken they are
>> detached.
>>
>> Signed-off-by: Janani Venkataraman <jananive@linux.vnet.ibm.com>
>> ---
>> +/* Gets the Thread IDS and siezes them */
>> +int seize_threads(int pid)
>> +{
>> +	char filename[40];
>> +	DIR *dir;
>> +	int ct = 0, ret = 0, tmp_tid;
>> +	struct dirent *entry;
>> +	char state;
>> +
>> +	ret = get_thread_count(pid);
>> +	if (ret == -1)
>> +		return -1;
>> +
>> +	cp.thread_count = ret;
>> +	cp.t_id = calloc(cp.thread_count, sizeof(int));
>> +	if (!cp.t_id) {
>> +		status = errno;
>> +		gencore_log("Could not allocate memory for thread_ids.\n");
>> +		return -1;
>> +	}
>> +
>> +	snprintf(filename, 40, "/proc/%d/task", pid);
>> +	dir = opendir(filename);
>> +
>> +	while ((entry = readdir(dir))) {
> This simple loop is not enough -- threads may appear and disappear while
> you do the readdir and seize, so you should scan it several times to
> make sure you caught all the threads.
>
> You can look at how this is done in CRIU in cr-dump,c:collect_threads().
>
If there are any new threads generated after the process is
issued a gencore, we need to ensure even those threads are
captured and seized. Hence we read the /proc/pid/task, till
no new threads are created.

We do a readdir again and again, till we find no new threads.
If a new thread is found, it is inserted in the right position.
This process is repeated till readdir reads no new threads.

Signed-off-by: Suzuki K. Poulose<suzuki@in.ibm.com>
Signed-off-by: Janani Venkataraman<jananive@linux.vnet.ibm.com>
---
  src/coredump.c |  161 +++++++++++++++++++++++++++++++++++++++++---------------
  1 file changed, 117 insertions(+), 44 deletions(-)

diff --git a/src/coredump.c b/src/coredump.c
index 49af7b3..2247ba2 100644
--- a/src/coredump.c
+++ b/src/coredump.c
@@ -93,68 +93,141 @@ void init_core(void)
  	memset(&cp, 0, sizeof(struct core_proc));
  }

-/* Gets the Thread IDS and siezes them */
-int seize_threads(int pid)
+/* Check if a particular TID is already added to cp.t_id */
+int search(int pid, int n)
  {
-	char filename[40];
-	DIR *dir;
-	int ct = 0, ret = 0, tmp_tid;
-	struct dirent *entry;
-	char state;
+	int first, last, middle;
+
+	first = 0;
+	last = n - 1;
+
+	while( first <= last ) {
+		
+		middle = (first + last)/2;
+
+		if ( cp.t_id[middle] < pid )
+			first = middle + 1;
+		else if ( cp.t_id[middle] == pid )
+			return 1;
+		else
+			last = middle - 1;
+	}

-	ret = get_thread_count(pid);
-	if (ret == -1)
-		return -1;
+	return 0;
+}

-	cp.thread_count = ret;
-	cp.t_id = calloc(cp.thread_count, sizeof(int));
-	if (!cp.t_id) {
-		status = errno;
-		gencore_log("Could not allocate memory for thread_ids.\n");
-		return -1;
+/* Insert a TID to cp.t_id */
+void insert (int tid, int n)
+{
+	int i, j, flag = 0;
+
+	for (i = 0; (i < n) && (tid > cp.t_id[i]); i++);
+
+	j = i;
+	while (j < n) {
+		cp.t_id[j + 1] = cp.t_id[j];
+		j++;
  	}

+	cp.t_id[i] = tid;
+}
+
+/*
+ * Read the directory /proc/pid/task again and again
+ * till we find no new threads.
+ */
+int scan_threads(int pid)
+{
+	DIR *dir;
+	struct dirent *entry;
+	int tmp_tid, ret = 0, k = 0;
+	char state;
+	char filename[40];
+
  	snprintf(filename, 40, "/proc/%d/task", pid);
+	
  	dir = opendir(filename);

  	while ((entry = readdir(dir))) {
  		if (entry->d_type == DT_DIR && entry->d_name[0] != '.') {
  			tmp_tid = atoi(entry->d_name);
-			ret = ptrace(PTRACE_SEIZE, tmp_tid, 0, 0);
-			if (ret) {
-				state = get_thread_status(tmp_tid);
-				if (state == 'Z')
-					goto assign;
-				status = errno;
-				gencore_log("Could not seize thread: %d\n",
-								tmp_tid);
-				break;
-			}
-			ret = ptrace(PTRACE_INTERRUPT, tmp_tid, 0, 0);
-			if (ret) {
-				state = get_thread_status(tmp_tid);
-				if (state == 'Z')
-					goto assign;
-				status = errno;
-				gencore_log("Could not interrupt thread: %d\n",
-								tmp_tid);
-				break;
-			}
-assign:
-			/* If a new thread, is created after we fetch the thread_count,
-			 * we may encounter a buffer overflow situation in the cp_tid.
-			 * Hence we check this case and re-allocate memory if required.
+			/*
+			 * Search for the thread, if not present, seize, interrupt
+			 * and insert it in cp.t_id.
  			 */
-			cp.t_id[ct++] = tmp_tid;
+			if (!search(tmp_tid, cp.thread_count)) {
+
+				k++;
+
+				ret = ptrace(PTRACE_SEIZE, tmp_tid, 0, 0);
+				if (ret) {
+					state = get_thread_status(tmp_tid);
+					if (state == 'Z')
+						goto assign;
+					status = errno;
+					gencore_log("Could not seize thread: %d\n",
+							tmp_tid);
+					break;
+				}
+
+				ret = ptrace(PTRACE_INTERRUPT, tmp_tid, 0, 0);
+				if (ret) {
+					state = get_thread_status(tmp_tid);
+					if (state == 'Z')
+						goto assign;
+					status = errno;
+					gencore_log("Could not interrupt thread: %d\n",
+							tmp_tid);
+					break;
+				}
+assign:
+				cp.t_id = (char *) realloc(cp.t_id, (cp.thread_count + 1) * sizeof(int));
+				if (!cp.t_id) {
+					status = errno;
+					gencore_log("Could not allocate memory for thread_ids.\n");
+					return -1;
+				}
+
+				insert(tmp_tid, cp.thread_count);
+				cp.thread_count ++;
+			}
  		}
  	}

-	/* Reassigning based on successful seizes */
-	cp.thread_count = ct;
-
  	closedir(dir);

+	if (!k)
+		return 1;
+
+	return ret;
+}
+
+/* Gets the Thread IDS and siezes them */
+int seize_threads(int pid)
+{
+	int ret = 0;
+
+	cp.thread_count = 0;
+	cp.t_id = calloc(cp.thread_count, sizeof(int));
+	if (!cp.t_id) {
+		status = errno;
+		gencore_log("Could not allocate memory for thread_ids.\n");
+		return -1;
+	}
+
+	/*
+	 * Read the directory /proc/pid/task again and again
+	 * till we find no new threads.
+	 */
+
+	do {
+		ret = scan_threads(pid);
+	} while (ret == 0);
+
  	/* Successful seize and interrupt on all threads makes ret = 0 */
+	if (ret == 1)
+		return 0;
+
  	return ret;
  }


Thanks.
Janani


[-- Attachment #2: Type: text/html, Size: 6968 bytes --]

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure
  2014-03-24 13:54       ` Phillip Susi
@ 2014-07-03 12:59         ` Suzuki K. Poulose
  0 siblings, 0 replies; 44+ messages in thread
From: Suzuki K. Poulose @ 2014-07-03 12:59 UTC (permalink / raw)
  To: Phillip Susi, Janani Venkataraman, Karel Zak
  Cc: amwang, rdunlap, andi, aravinda, hch, mhiramat,
	jeremy.fitzhardinge, xemul, suzuki, kosaki.motohiro, adobriyan,
	tarundsk, vapier, roland, tj, ananth, gorcunov, avagin, oleg,
	eparis, d.hatayama, james.hogan, akpm, torvalds, coreutils,
	procps, util-linux, linux-kernel

On 03/24/2014 07:24 PM, Phillip Susi wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> On 3/24/2014 5:43 AM, Janani Venkataraman wrote:
>> Gcore attaches to the process using gdb and runs the gdb gcore
>> command and then detaches. In gcore the dump cannot be issued from
>> a signal handler context as fork() is not signal safe and moreover
>> it is disruptive in
> 
> You can fork+exec from a signal handler just fine.
Please go through the bug, and especially the comment below :

https://sourceware.org/bugzilla/show_bug.cgi?id=4737#c12

Cheers
Suzuki


^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2014-07-03 12:59 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-20  9:39 [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Janani Venkataraman
2014-03-20  9:39 ` [PATCH 01/33] Configure and Make files Janani Venkataraman
2014-03-20  9:39 ` [PATCH 02/33] Validity of arguments Janani Venkataraman
2014-03-20  9:39 ` [PATCH 03/33] Process Status Janani Venkataraman
2014-03-20  9:39 ` [PATCH 04/33] Hold threads Janani Venkataraman
2014-03-20 19:01   ` Pavel Emelyanov
2014-03-25  6:58     ` Janani Venkataraman
2014-04-18 14:04     ` Janani Venkataraman
2014-03-20  9:39 ` [PATCH 05/33] Fetching Memory maps Janani Venkataraman
2014-03-20  9:39 ` [PATCH 06/33] Check ELF class Janani Venkataraman
2014-03-20  9:39 ` [PATCH 07/33] Do elf_coredump Janani Venkataraman
2014-03-20  9:40 ` [PATCH 08/33] Fills elf header Janani Venkataraman
2014-03-20  9:40 ` [PATCH 09/33] Adding notes infrastructure Janani Venkataraman
2014-03-20  9:40 ` [PATCH 10/33] Populates PRPS info Janani Venkataraman
2014-03-20  9:40 ` [PATCH 11/33] Populate AUXV Janani Venkataraman
2014-03-20  9:40 ` [PATCH 12/33] Fetch File maps Janani Venkataraman
2014-03-20  9:41 ` [PATCH 13/33] Fetching thread specific Notes Janani Venkataraman
2014-03-20  9:41 ` [PATCH 14/33] Populating Program Headers Janani Venkataraman
2014-03-20  9:41 ` [PATCH 15/33] Updating Offset Janani Venkataraman
2014-03-20  9:41 ` [PATCH 16/33] Writing to core file Janani Venkataraman
2014-03-20  9:41 ` [PATCH 17/33] Daemonizing the Process Janani Venkataraman
2014-03-20  9:41 ` [PATCH 18/33] Socket operations Janani Venkataraman
2014-03-20  9:41 ` [PATCH 19/33] Block till request Janani Venkataraman
2014-03-20  9:41 ` [PATCH 20/33] Handling Requests Janani Venkataraman
2014-03-20  9:41 ` [PATCH 21/33] Get Clients PID Janani Venkataraman
2014-03-20  9:41 ` [PATCH 22/33] Dump the task Janani Venkataraman
2014-03-20  9:42 ` [PATCH 23/33] Handling SIG TERM of the daemon Janani Venkataraman
2014-03-20  9:42 ` [PATCH 24/33] Handling SIG TERM of the child Janani Venkataraman
2014-03-20  9:42 ` [PATCH 25/33] Systemd Socket ID retrieval Janani Venkataraman
2014-03-20  9:42 ` [PATCH 26/33] [libgencore] Setting up Connection Janani Venkataraman
2014-03-20  9:42 ` [PATCH 27/33] [libgencore] Request for dump Janani Venkataraman
2014-03-20  9:43 ` [PATCH 28/33] Man pages Janani Venkataraman
2014-03-20  9:43 ` [PATCH 29/33] Automake files for the doc folder Janani Venkataraman
2014-03-20  9:43 ` [PATCH 30/33] README, COPYING, Changelog Janani Venkataraman
2014-03-20  9:43 ` [PATCH 31/33] Spec file Janani Venkataraman
2014-03-20  9:43 ` [PATCH 32/33] Socket and Service files Janani Venkataraman
2014-03-20  9:44 ` [PATCH 33/33] Support check Janani Venkataraman
2014-03-20 10:24 ` [PATCH 00/33] [RFC] Non disruptive application core dump infrastructure Pádraig Brady
2014-03-21  8:17 ` Karel Zak
2014-03-21 15:02   ` Phillip Susi
2014-03-24  9:43     ` Janani Venkataraman
2014-03-24 13:54       ` Phillip Susi
2014-07-03 12:59         ` Suzuki K. Poulose
2014-03-24  9:38   ` Janani Venkataraman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.