summaryrefslogtreecommitdiff
path: root/src/core_dump_handler/dlt_cdh_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core_dump_handler/dlt_cdh_context.c')
-rw-r--r--src/core_dump_handler/dlt_cdh_context.c407
1 files changed, 407 insertions, 0 deletions
diff --git a/src/core_dump_handler/dlt_cdh_context.c b/src/core_dump_handler/dlt_cdh_context.c
new file mode 100644
index 0000000..4fb1d85
--- /dev/null
+++ b/src/core_dump_handler/dlt_cdh_context.c
@@ -0,0 +1,407 @@
+/*
+ * @licence app begin@
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2011-2015, BMW AG
+ *
+ * This file is part of GENIVI Project DLT - Diagnostic Log and Trace.
+ *
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License (MPL), v. 2.0.
+ * If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+/*!
+ * \author Magneti Marelli http://www.magnetimarelli.com
+ * \author Lutz Helwing <lutz_helwing@mentor.com>
+ *
+ * \copyright Copyright © 2011-2015 BMW AG. \n
+ * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
+ *
+ * \file dlt_cdh_context.c
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <dirent.h>
+#include <syslog.h>
+
+#include "dlt_cdh.h"
+
+// Global buffer for file reading
+char g_buffer[4096];
+
+/* ===================================================================
+ ** Method : get_exec_name(...)
+ **
+ ** Description : read executable filename
+ **
+ ** Parameters : INPUT p_pid_str pid of the process
+ ** OUTPUT p_exec_name executable name
+ ** INPUT p_exec_name_maxsize size of p_exec_name buffer
+ **
+ ** Returns : 0 if success, else -1
+ ** ===================================================================*/
+cdh_status_t get_exec_name(unsigned int p_pid, char* p_exec_name, int p_exec_name_maxsize)
+{
+ char l_exe_link[CORE_MAX_FILENAME_LENGTH] = { 0 };
+ char *l_name_ptr = NULL;
+
+ memset(l_exe_link, 0, sizeof(l_exe_link));
+ snprintf(l_exe_link, sizeof(l_exe_link) - 1, "/proc/%d/exe", p_pid);
+
+ if (readlink(l_exe_link, g_buffer, p_exec_name_maxsize) < 0)
+ return CDH_NOK;
+
+ if ((l_name_ptr = strrchr(g_buffer, '/')) == NULL)
+ return CDH_NOK;
+
+ memset(p_exec_name, 0, p_exec_name_maxsize);
+ strncpy(p_exec_name, l_name_ptr + 1, p_exec_name_maxsize - 1);
+
+ return CDH_OK;
+}
+
+/* ===================================================================
+ ** Method : dump_file_to(...)
+ **
+ ** Description : dump the content of file p_src_filename to the file descriptor p_fout
+ **
+ ** Parameters : INPUT p_src_filename
+ ** INPUT p_fout
+ **
+ ** Returns : 0 if success, else -1
+ ** ===================================================================*/
+cdh_status_t dump_file_to(const char* p_src_filename, FILE* p_fout)
+{
+ FILE* l_fin = NULL;
+ int bytes_read = 0;
+
+ if (p_fout == NULL)
+ return CDH_NOK;
+
+ fprintf(p_fout, "\n==== Dumping file <%s> ====\n", p_src_filename);
+
+ if ((l_fin = fopen(p_src_filename, "rt")) == NULL)
+ {
+ syslog(LOG_ERR, "ERR opening info file '%s' for dumping [%s]",
+ p_src_filename,
+ strerror(errno));
+
+ fprintf(p_fout, "**error**\n");
+
+ return CDH_NOK;
+ }
+
+ while ((bytes_read = fread(g_buffer, 1, sizeof(g_buffer), l_fin)) != 0)
+ {
+ int i = 0;
+
+ // changes all "\0" in the file to a "\n"
+ // (needed for example for /proc/<pid>/cmdline, to keep all arguments)
+ for (i = 0; i < bytes_read; i++)
+ {
+ if (g_buffer[i] == '\000')
+ g_buffer[i] = '\n';
+ }
+
+ fwrite(g_buffer, 1, bytes_read, p_fout);
+ if (ferror(p_fout))
+ {
+ syslog(LOG_ERR, "Writing in context file failed [%s]", strerror(errno));
+ fclose(p_fout);
+ fclose(l_fin);
+
+ return CDH_NOK;
+
+ }
+ }
+
+ if (ferror(l_fin))
+ {
+ syslog(LOG_ERR, "reading '%s' failed [%s]", p_src_filename, strerror(errno));
+ fclose(l_fin);
+
+ return CDH_NOK;
+ }
+
+ fclose(l_fin);
+
+ fprintf(p_fout, "\n");
+ return CDH_OK;
+}
+
+//*************************************************************************************************/
+// "ls -l" implementation for /proc/<pid>/fd (at least)
+// Taken from coreutils sources, lib/filemode.c
+//
+/* Return a character indicating the type of file described by
+ file mode BITS:
+ '-' regular file
+ 'b' block special file
+ 'c' character special file
+ 'C' high performance ("contiguous data") file
+ 'd' directory
+ 'D' door
+ 'l' symbolic link
+ 'm' multiplexed file (7th edition Unix; obsolete)
+ 'n' network special file (HP-UX)
+ 'p' fifo (named pipe)
+ 'P' port
+ 's' socket
+ 'w' whiteout (4.4BSD)
+ '?' some other file type */
+
+static char ftypelet(mode_t bits)
+{
+ /* These are the most common, so test for them first. */
+ if (S_ISREG(bits))
+ return '-';
+ if (S_ISDIR(bits))
+ return 'd';
+
+ /* Other letters standardized by POSIX 1003.1-2004. */
+ if (S_ISBLK(bits))
+ return 'b';
+ if (S_ISCHR(bits))
+ return 'c';
+ if (S_ISLNK(bits))
+ return 'l';
+ if (S_ISFIFO(bits))
+ return 'p';
+
+ /* Other file types (though not letters) standardized by POSIX. */
+ if (S_ISSOCK(bits))
+ return 's';
+
+ /* Nonstandard file types.
+ if (S_ISCTG (bits))
+ return 'C';
+ if (S_ISDOOR (bits))
+ return 'D';
+ if (S_ISMPB (bits) || S_ISMPC (bits))
+ return 'm';
+ if (S_ISNWK (bits))
+ return 'n';
+ if (S_ISPORT (bits))
+ return 'P';
+ if (S_ISWHT (bits))
+ return 'w';
+ */
+
+ return '?';
+}
+
+void strmode(mode_t mode, char *str)
+{
+ if (str == NULL)
+ return;
+
+ str[0] = ftypelet(mode);
+ str[1] = mode & S_IRUSR ? 'r' : '-';
+ str[2] = mode & S_IWUSR ? 'w' : '-';
+ str[3] = (mode & S_ISUID
+ ? (mode & S_IXUSR ? 's' : 'S')
+ :
+ (mode & S_IXUSR ? 'x' : '-'));
+ str[4] = mode & S_IRGRP ? 'r' : '-';
+ str[5] = mode & S_IWGRP ? 'w' : '-';
+ str[6] = (mode & S_ISGID
+ ? (mode & S_IXGRP ? 's' : 'S')
+ :
+ (mode & S_IXGRP ? 'x' : '-'));
+ str[7] = mode & S_IROTH ? 'r' : '-';
+ str[8] = mode & S_IWOTH ? 'w' : '-';
+ str[9] = (mode & S_ISVTX
+ ? (mode & S_IXOTH ? 't' : 'T')
+ :
+ (mode & S_IXOTH ? 'x' : '-'));
+ str[10] = ' ';
+ str[11] = '\0';
+}
+
+/* ===================================================================
+ ** Method : list_dircontent_to(...)
+ **
+ ** Description : list the filenames in p_dirname directory to the file descriptor p_fout
+ **
+ ** Parameters : INPUT p_dirname
+ ** INPUT p_fout
+ **
+ ** Returns : 0 if success, else -1
+ ** ===================================================================*/
+cdh_status_t list_dircontent_to(const char* p_dirname, FILE* p_fout)
+{
+ DIR* l_dd = NULL; // directory descriptor
+ struct dirent* l_entity = NULL;
+
+ if ((l_dd = opendir(p_dirname)) == NULL)
+ {
+ syslog(LOG_ERR, "ERR reading info dir '%s' failed [%s]", p_dirname, strerror(errno));
+ return CDH_NOK;
+ }
+
+ fprintf(p_fout, "==== Listing directory <%s> ====\n", p_dirname);
+
+ while ((l_entity = readdir(l_dd)) != NULL)
+ {
+ char l_fullpath[CORE_MAX_FILENAME_LENGTH] = { 0 };
+ char l_linkpath[CORE_MAX_FILENAME_LENGTH] = { 0 };
+ char l_modebuf[12] = { 0 };
+
+ struct stat l_stat;
+ ssize_t l_size = 0;
+
+ if (!strcmp(l_entity->d_name, ".") || !strcmp(l_entity->d_name, ".."))
+ continue;
+
+ snprintf(l_fullpath, sizeof(l_fullpath), "%s/%s", p_dirname, l_entity->d_name);
+
+ if (lstat(l_fullpath, &l_stat) < 0)
+ {
+ syslog(LOG_ERR, "ERR lstat on '%s' failed. [%s]", l_fullpath, strerror(errno));
+ continue;
+ }
+
+ strmode(l_stat.st_mode, l_modebuf);
+
+ fprintf(p_fout, "%s %ld %d %d %ld %4s",
+ l_modebuf,
+ l_stat.st_nlink,
+ l_stat.st_uid,
+ l_stat.st_gid,
+ l_stat.st_size,
+ l_entity->d_name);
+
+ switch (l_stat.st_mode & S_IFMT)
+ {
+ case S_IFBLK:
+ fprintf(p_fout, " [block device]\n");
+ break;
+
+ case S_IFCHR:
+ fprintf(p_fout, " [character device]\n");
+ break;
+
+ case S_IFDIR:
+ fprintf(p_fout, " [directory]\n");
+ break;
+
+ case S_IFIFO:
+ fprintf(p_fout, " [FIFO/pipe]\n");
+ break;
+
+ case S_IFLNK:
+ l_size = readlink(l_fullpath, l_linkpath, sizeof(l_linkpath));
+ l_linkpath[l_size] = 0;
+ fprintf(p_fout, " -> %s\n", l_linkpath);
+ break;
+
+ case S_IFREG:
+ fprintf(p_fout, " [regular file]\n");
+ break;
+
+ case S_IFSOCK:
+ fprintf(p_fout, " [socket]\n");
+ break;
+
+ default:
+ fprintf(p_fout, " [unknown?]\n");
+ break;
+ }
+
+ } // while ( (l_entity = readdir(l_dd)) != NULL )
+
+ fprintf(p_fout, "===========================\n");
+ closedir(l_dd);
+
+ return CDH_OK;
+}
+
+//*************************************************************************************************/
+// END of "ls -l" implementation for /proc/<pid>/fd (at least)
+//*************************************************************************************************/
+
+/* ===================================================================
+ ** Method : write_proc_context(...)
+ **
+ ** Description : write the context data of the crashed process
+ ** (context data coming mainly from /proc)
+ **
+ ** Parameters : INPUT p_proc crashed process info
+ **
+ ** Returns : 0 if success, else -1
+ ** ===================================================================*/
+cdh_status_t write_proc_context(const proc_info_t* p_proc)
+{
+ FILE* l_fout = NULL;
+ char l_procfile[256] = { 0 };
+ char l_outfilename[CORE_MAX_FILENAME_LENGTH] = { 0 };
+
+ if (p_proc == NULL)
+ return CDH_NOK;
+
+ snprintf(l_outfilename, sizeof(l_outfilename), CONTEXT_FILE_PATTERN,
+ CORE_TMP_DIRECTORY,
+ p_proc->timestamp,
+ p_proc->name,
+ p_proc->pid);
+
+ if ((l_fout = fopen(l_outfilename, "w+t")) == NULL)
+ {
+ syslog(LOG_ERR, "ERR Cannot open context file '%s' [%s]", l_outfilename, strerror(errno));
+ return CDH_NOK;
+ }
+
+#define PROC_FILENAME(x) do{\
+ snprintf(l_procfile, sizeof(l_procfile), "/proc/%d/"x,\
+ p_proc->pid);\
+} while(0)
+
+ fprintf(l_fout, "ProcName:%s\n", p_proc->name);
+ fprintf(l_fout, "ThreadName:%s\n", p_proc->threadname);
+ fprintf(l_fout, "PID:%d\n", p_proc->pid);
+ fprintf(l_fout, "signal:%d\n", p_proc->signal);
+
+ PROC_FILENAME("cmdline");
+ dump_file_to(l_procfile, l_fout);
+
+ PROC_FILENAME("cgroup");
+ dump_file_to(l_procfile, l_fout);
+
+ PROC_FILENAME("stack");
+ dump_file_to(l_procfile, l_fout);
+
+ dump_file_to("/proc/loadavg", l_fout);
+ dump_file_to("/etc/sysrel", l_fout);
+ dump_file_to("/proc/version", l_fout);
+
+ PROC_FILENAME("environ");
+ dump_file_to(l_procfile, l_fout);
+
+ PROC_FILENAME("status");
+ dump_file_to(l_procfile, l_fout);
+
+ PROC_FILENAME("sched");
+ dump_file_to(l_procfile, l_fout);
+
+ PROC_FILENAME("maps");
+ dump_file_to(l_procfile, l_fout);
+
+ PROC_FILENAME("fd");
+ list_dircontent_to(l_procfile, l_fout);
+
+#undef PROC_FILENAME
+
+ fflush(l_fout);
+
+ return CDH_OK;
+}
+