]> git.itanic.dy.fi Git - scan-pagemap/blob - main.c
9f9b5c54c7e1cbf90eeb56dc9ab982028718936c
[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                 "-h, --help             show this help\n",
22                 name);
23
24         exit(0);
25 }
26
27 #define OPT_WITH_THREADS        0x101
28
29 static void get_all_pids_by_name(struct parse_opts *opts, char *name)
30 {
31         struct pidlist *pidlist;
32         DIR *dir = NULL;
33         int pid;
34
35         while ((pid = get_next_pid_by_name(&dir, name))) {
36                 pidlist = alloc_pidlist();
37                 if (pidlist == NULL)
38                         return;
39                 pidlist->pid = pid;
40                 list_add_tail(&pidlist->list, &opts->pidlist);
41         }
42 }
43
44 void read_args(int argc, char *argv[], struct parse_opts *opts)
45 {
46         int optind = 0, c;
47         static struct option long_options[] = {
48                 { .val = 'p', .name = "pid", .has_arg = 1, },
49                 { .val = 'P', .name = "process", .has_arg = 1, },
50                 { .val = 'm', .name = "map", .has_arg = 1, },
51                 { .val = OPT_WITH_THREADS, .name = "with-threads" },
52                 { .val = 'd', .name = "dump", },
53                 { .val = 'h', .name = "help", },
54         };
55         char short_options[] = "p:P:m:dh";
56         opts->parse_mask = 0;
57
58         while (1) {
59                 c = getopt_long(argc, argv, short_options, long_options,
60                                 &optind);
61
62                 if (c == -1)
63                         break;
64
65                 switch (c) {
66                 case 'p':
67                 {
68                         struct pidlist *pid = alloc_pidlist();
69
70                         if (pid == NULL) {
71                                 perror("malloc");
72                                 return;
73                         }
74                         pid->pid = atoi(optarg);
75                         opts->parse_mask |= PARSE_PID;
76                         list_add_tail(&pid->list, &opts->pidlist);
77                         break;
78                 }
79                 case 'P':
80                         get_all_pids_by_name(opts, optarg);
81                         opts->parse_mask |= PARSE_PID;
82                         break;
83                 case 'm':
84                         opts->parse_mask |= PARSE_MAP_NAME;
85                         opts->name = optarg;
86                         break;
87                 case OPT_WITH_THREADS:
88                         opts->with_threads = 1;
89                         break;
90                 case 'd':
91                         opts->parse_mask |= PARSE_DUMP;
92                         break;
93                 case 'h':
94                         print_help_and_die(argv[0]);
95                         break;
96                 }
97         }
98 }
99
100 int main(int argc, char *argv[])
101 {
102         struct pageframe pf;
103         struct process process_list;
104         struct parse_opts opts;
105
106         if (geteuid()) {
107                 printf("WARNING: Running without root priviledges. "
108                         "Results may be inaccurate\n");
109         }
110
111         init_parse_opts(&opts);
112
113         read_args(argc, argv, &opts);
114
115         if (argc < 3) {
116                 printf("A pid needs to be given as an argument\n");
117                 print_help_and_die(argv[0]);
118         }
119
120         clear_pageframe(&pf);
121
122         memset(&process_list, 0, sizeof(process_list));
123         INIT_LIST_HEAD(&process_list.list);
124
125         if (scan_all_pids(&pf, &process_list, &opts))
126                 return 1;
127
128         if (opts.parse_mask & PARSE_DUMP)
129                 dump_process_maps(&process_list);
130         else
131                 print_pid_stats(&pf, &process_list, &opts);
132
133         print_page_stats(&pf);
134
135         return 0;
136 }