]> git.itanic.dy.fi Git - scan-pagemap/blob - main.c
Add support for listing mappings that are shared between processes
[scan-pagemap] / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <getopt.h>
6 #include <unistd.h>
7 #include <sys/types.h>
8
9 #include "parse.h"
10 #include "analyze.h"
11 #include "pidlib.h"
12
13 void print_help_and_die(char *name)
14 {
15         printf("Usage: %s options\n"
16                 "-p, --pid=PID          scan maps belonging to a given pid\n"
17                 "-P, --process=PROCESS  scan maps belonging to processes with "
18                 "given name\n"
19                 "-m, --map=mapname      scan maps with given mapping name\n"
20                 "-d, --dump             dump process maps\n"
21                 "-s, --shared-mappings  dump only shared mappings\n"
22                 "-h, --help             show this help\n",
23                 name);
24
25         exit(0);
26 }
27
28 #define OPT_WITH_THREADS        0x101
29
30 static void get_all_pids_by_name(struct parse_opts *opts, char *name)
31 {
32         struct pidlist *pidlist;
33         DIR *dir = NULL;
34         int pid;
35
36         while ((pid = get_next_pid_by_name(&dir, name))) {
37                 pidlist = alloc_pidlist();
38                 if (pidlist == NULL)
39                         return;
40                 pidlist->pid = pid;
41                 list_add_tail(&pidlist->list, &opts->pidlist);
42         }
43 }
44
45 void read_args(int argc, char *argv[], struct parse_opts *opts)
46 {
47         int optind = 0, c;
48         static struct option long_options[] = {
49                 { .val = 'p', .name = "pid", .has_arg = 1, },
50                 { .val = 'P', .name = "process", .has_arg = 1, },
51                 { .val = 'm', .name = "map", .has_arg = 1, },
52                 { .val = OPT_WITH_THREADS, .name = "with-threads" },
53                 { .val = 'd', .name = "dump", },
54                 { .val = 's', .name = "shared-mappings", },
55                 { .val = 'h', .name = "help", },
56         };
57         char short_options[] = "p:P:m:sdh";
58         opts->parse_mask = 0;
59
60         while (1) {
61                 c = getopt_long(argc, argv, short_options, long_options,
62                                 &optind);
63
64                 if (c == -1)
65                         break;
66
67                 switch (c) {
68                 case 'p':
69                 {
70                         struct pidlist *pid = alloc_pidlist();
71
72                         if (pid == NULL) {
73                                 perror("malloc");
74                                 return;
75                         }
76                         pid->pid = atoi(optarg);
77                         opts->parse_mask |= PARSE_PID;
78                         list_add_tail(&pid->list, &opts->pidlist);
79                         break;
80                 }
81                 case 'P':
82                         get_all_pids_by_name(opts, optarg);
83                         opts->parse_mask |= PARSE_PID;
84                         break;
85                 case 'm':
86                         opts->parse_mask |= PARSE_MAP_NAME;
87                         opts->name = optarg;
88                         break;
89                 case OPT_WITH_THREADS:
90                         opts->with_threads = 1;
91                         break;
92                 case 's':
93                         opts->parse_mask |= PARSE_SHARED_MAPPING;
94                         /* implies --dump */
95                 case 'd':
96                         opts->parse_mask |= PARSE_DUMP;
97                         break;
98                 case 'h':
99                         print_help_and_die(argv[0]);
100                         break;
101                 }
102         }
103 }
104
105 int main(int argc, char *argv[])
106 {
107         struct pageframe pf;
108         struct process process_list;
109         struct parse_opts opts;
110
111         if (geteuid()) {
112                 printf("WARNING: Running without root priviledges. "
113                         "Results may be inaccurate\n");
114         }
115
116         init_parse_opts(&opts);
117
118         read_args(argc, argv, &opts);
119
120         if (argc < 3) {
121                 printf("A pid needs to be given as an argument\n");
122                 print_help_and_die(argv[0]);
123         }
124
125         clear_pageframe(&pf);
126
127         memset(&process_list, 0, sizeof(process_list));
128         INIT_LIST_HEAD(&process_list.list);
129
130         if (scan_all_pids(&pf, &process_list, &opts))
131                 return 1;
132
133         if (opts.parse_mask & PARSE_DUMP)
134                 dump_process_maps(&pf, &process_list, &opts);
135         else
136                 print_pid_stats(&pf, &process_list, &opts);
137
138         print_page_stats(&pf);
139
140         return 0;
141 }