* [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; 43+ 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] 43+ 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; 43+ 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] 43+ 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; 43+ 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] 43+ 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; 43+ 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] 43+ 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
0 siblings, 1 reply; 43+ 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] 43+ messages in thread* Re: [PATCH 04/33] Hold threads
2014-03-20 19:01 ` Pavel Emelyanov
@ 2014-03-25 6:58 ` Janani Venkataraman
0 siblings, 0 replies; 43+ 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] 43+ 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; 43+ 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] 43+ 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; 43+ 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] 43+ 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; 43+ 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] 43+ 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; 43+ 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] 43+ 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; 43+ 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] 43+ 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; 43+ 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] 43+ 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; 43+ 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] 43+ 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; 43+ 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] 43+ 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; 43+ 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] 43+ 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; 43+ 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] 43+ 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; 43+ 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] 43+ 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; 43+ 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