crash-pipe: Print maps information 16/96916/2
authorŁukasz Stelmach <l.stelmach@samsung.com>
Fri, 4 Nov 2016 09:43:52 +0000 (10:43 +0100)
committerŁukasz Stelmach <l.stelmach@samsung.com>
Thu, 8 Dec 2016 13:43:13 +0000 (14:43 +0100)
Change-Id: Idab48c5dde20e0aa2a8337b7008a8244a612d844

src/crash-pipe/crash-pipe.c

index 90cf2d7f01a6a17873c21cde8b9fb3da484adfd1..187995bb50e37c6562ef9ddb6b7d979fb49e927f 100644 (file)
@@ -27,6 +27,7 @@
 #include <sys/prctl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/mman.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <getopt.h>
 
 #define NELEMS(arr) (sizeof(arr)/sizeof(arr[0]))
 #define BUF_SIZE (BUFSIZ)
+#define HEXA 16
+#define PERM_LEN 5
+#define ADDR_LEN 16
+#define STR_ANONY "[anony]"
+#define STR_ANONY_LEN 8
 
 enum {
        OPT_HELP,
@@ -41,6 +47,14 @@ enum {
        OPT_SAVE_CORE,
 };
 
+struct addr_node {
+       long *startaddr;
+       long *endaddr;
+       char perm[5];
+       char *fpath;
+       struct addr_node *next;
+};
+
 const struct option opts[] = {
        { "help", no_argument, 0, OPT_HELP },
        { "report", no_argument, 0, OPT_REPORT },
@@ -131,7 +145,8 @@ static char *fgets_fd(char *str, int len, int fd)
         return (num == 0 && cs == str) ? NULL : str;
 }
 
-static void meminfo_report(const char *pidstr){
+static void meminfo_report(const char *pidstr)
+{
        char infoname[BUF_SIZE];
        char memsize[BUF_SIZE];
        char linebuf[BUF_SIZE];
@@ -208,6 +223,139 @@ static void meminfo_report(const char *pidstr){
         }
 }
 
+static struct addr_node *get_addr_list_from_maps(int fd)
+{
+        int fpath_len, result;
+        long *saddr;
+        long *eaddr;
+        char perm[PERM_LEN];
+        char path[PATH_MAX];
+        char addr[ADDR_LEN * 2];
+        char linebuf[BUF_SIZE];
+        struct addr_node *head = NULL;
+        struct addr_node *tail = NULL;
+        struct addr_node *t_node = NULL;
+
+        /* parsing the maps to get executable code address */
+        while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) {
+                memset(path, 0, PATH_MAX);
+                result = sscanf(linebuf, "%s %s %*s %*s %*s %s ", addr, perm, path);
+                if (result < 0)
+                        continue;
+                perm[PERM_LEN - 1] = 0;
+                /* rwxp */
+                if ((perm[2] == 'x' && path[0] == '/') ||
+                   (perm[1] == 'w' && path[0] != '/'))
+               {
+                       /* add addr node to list */
+                       addr[ADDR_LEN] = 0;
+                       saddr = (long *)strtoul(addr, NULL, HEXA);
+                       /* ffff0000-ffff1000 */
+                       eaddr = (long *)strtoul(&addr[ADDR_LEN + 1], NULL, HEXA);
+                       /* make node and attach to the list */
+                       t_node = (struct addr_node *)mmap(0, sizeof(struct addr_node),
+                                                         PROT_READ | PROT_WRITE,
+                                                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+                       if (t_node == NULL) {
+                               fprintf(stderr, "error : mmap\n");
+                               return NULL;
+                       }
+                       memcpy(t_node->perm, perm, PERM_LEN);
+                       t_node->startaddr = saddr;
+                       t_node->endaddr = eaddr;
+                       t_node->fpath = NULL;
+                       fpath_len = strlen(path);
+                       if (fpath_len > 0) {
+                               t_node->fpath = (char *)mmap(0, fpath_len + 1,
+                                                            PROT_READ | PROT_WRITE,
+                                                            MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+                               memset(t_node->fpath, 0, fpath_len + 1);
+                               memcpy(t_node->fpath, path, fpath_len);
+                       } else {
+                               t_node->fpath = (char *)mmap(0, STR_ANONY_LEN,
+                                                            PROT_READ | PROT_WRITE,
+                                                            MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+                               memset(t_node->fpath, 0, STR_ANONY_LEN);
+                               memcpy(t_node->fpath, STR_ANONY, STR_ANONY_LEN);
+                       }
+                       t_node->next = NULL;
+                       if (head == NULL) {
+                               head = t_node;
+                               tail = t_node;
+                       } else {
+                               tail->next = t_node;
+                               tail = t_node;
+                       }
+               }
+       }
+       return head;
+}
+
+static void free_all_nodes(struct addr_node *start)
+{
+       struct addr_node *t_node, *n_node;
+       int fpath_len;
+
+       if (start == NULL)
+               return;
+       t_node = start;
+       n_node = t_node->next;
+       while (t_node) {
+               if (t_node->fpath != NULL) {
+                       fpath_len = strlen(t_node->fpath);
+                       munmap(t_node->fpath, fpath_len + 1);
+               }
+               munmap(t_node, sizeof(struct addr_node));
+               if (n_node == NULL)
+                       break;
+               t_node = n_node;
+               n_node = n_node->next;
+       }
+}
+
+static void print_node_to_file(struct addr_node *start)
+{
+       struct addr_node *t_node;
+
+       t_node = start;
+       printf("\n%s\n", "Maps Information");
+       while (t_node) {
+               if (!strncmp(STR_ANONY, t_node->fpath, STR_ANONY_LEN)) {
+                       t_node = t_node->next;
+               } else {
+                       printf( "%16lx %16lx %s %s\n",
+                               (unsigned long)t_node->startaddr,
+                               (unsigned long)t_node->endaddr,
+                               t_node->perm, t_node->fpath);
+                       t_node = t_node->next;
+               }
+       }
+       printf("%s\n", "End of Maps Information");
+}
+
+static void maps_report(const char *pidstr)
+{
+       char file_path[PATH_MAX];
+       struct addr_node *head = NULL;
+       int fd;
+
+       /* open maps file */
+       snprintf(file_path, PATH_MAX, "/proc/%s/maps", pidstr);
+
+        if ((fd = open(file_path, O_RDONLY)) < 0) {
+                fprintf(stderr, "[crash-pipe]can't open %s\n", file_path);
+        } else {
+                /* parsing the maps to get code segment address*/
+                head = get_addr_list_from_maps(fd);
+                close(fd);
+        }
+       if (head != NULL) {
+               /* print maps information */
+               print_node_to_file(head);
+               free_all_nodes(head);
+       }
+}
+
 static void report(int argc, char *argv[])
 {
        const char *pidstr = argv[0];
@@ -245,6 +393,8 @@ static void report(int argc, char *argv[])
 
        meminfo_report(pidstr);
 
+       maps_report(pidstr);
+
        printf(" - passed from kernel -\n"
                   "%16s: %s\n"
                   "%16s: %s\n"