• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <error.h>
18 #include <inttypes.h>
19 #include <linux/kernel-page-flags.h>
20 #include <stdlib.h>
21 #include <sys/mman.h>
22 #include <sys/types.h>
23 
24 #include <iostream>
25 #include <map>
26 #include <memory>
27 #include <set>
28 
29 #include <android-base/parseint.h>
30 #include <android-base/strings.h>
31 #include <meminfo/procmeminfo.h>
32 
33 #include <processrecord.h>
34 #include <smapinfo.h>
35 
36 using ::android::meminfo::Format;
37 using ::android::meminfo::GetFormat;
38 using ::android::smapinfo::SortOrder;
39 
usage(int exit_status)40 [[noreturn]] static void usage(int exit_status) {
41     std::cerr << "Usage: " << getprogname() << " [ -P | -L ] [ -v | -r | -p | -u | -s | -h ]\n"
42               << "\n"
43               << "Sort options:\n"
44               << "    -v  Sort processes by VSS.\n"
45               << "    -r  Sort processes by RSS.\n"
46               << "    -p  Sort processes by PSS.\n"
47               << "    -u  Sort processes by USS.\n"
48               << "    -o  Sort (and show) processes by oom score.\n"
49               << "    -s  Sort processes by swap.\n"
50               << "        (Default sort order is PSS.)\n"
51               << "    -a  Show all mappings, including stack, heap and anon.\n"
52               << "    -P /path  Limit libraries displayed to those in path.\n"
53               << "    -R  Reverse sort order (default is descending).\n"
54               << "    -m [r][w][x] Only list pages that exactly match permissions\n"
55               << "    -c  Only show cached (storage backed) pages\n"
56               << "    -C  Only show non-cached (ram/swap backed) pages\n"
57               << "    -k  Only show pages collapsed by KSM\n"
58               << "    -f  [raw][json][csv] Print output in the specified format.\n"
59               << "        (Default format is raw text.)\n"
60               << "    -h  Display this help screen.\n";
61     exit(exit_status);
62 }
63 
parse_mapflags(const char * mapflags)64 static uint16_t parse_mapflags(const char* mapflags) {
65     uint16_t ret = 0;
66     for (const char* p = mapflags; *p; p++) {
67         switch (*p) {
68             case 'r':
69                 ret |= PROT_READ;
70                 break;
71             case 'w':
72                 ret |= PROT_WRITE;
73                 break;
74             case 'x':
75                 ret |= PROT_EXEC;
76                 break;
77             default:
78                 error(EXIT_FAILURE, 0, "Invalid permissions string: %s, %s", mapflags, p);
79         }
80     }
81     return ret;
82 }
83 
main(int argc,char * argv[])84 int main(int argc, char* argv[]) {
85     uint64_t pgflags = 0;
86     uint64_t pgflags_mask = 0;
87 
88     // Library filtering options.
89     std::string lib_prefix = "";
90     bool all_libs = false;
91     std::vector<std::string> excluded_libs = {"[heap]", "[stack]"};
92     uint16_t mapflags_mask = 0;
93 
94     // Output format (raw text, JSON, CSV).
95     Format format = Format::RAW;
96 
97     // Process sorting options.
98     SortOrder sort_order = SortOrder::BY_PSS;
99     bool reverse_sort = false;
100 
101     int opt;
102     while ((opt = getopt(argc, argv, "acCf:hkm:opP:uvrsR")) != -1) {
103         switch (opt) {
104             case 'a':
105                 all_libs = true;
106                 break;
107             case 'c':
108                 pgflags = 0;
109                 pgflags_mask = (1 << KPF_SWAPBACKED);
110                 break;
111             case 'C':
112                 pgflags = (1 << KPF_SWAPBACKED);
113                 pgflags_mask = (1 << KPF_SWAPBACKED);
114                 break;
115             case 'f':
116                 format = GetFormat(optarg);
117                 if (format == Format::INVALID) {
118                     std::cerr << "Invalid format." << std::endl;
119                     usage(EXIT_FAILURE);
120                 }
121                 break;
122             case 'h':
123                 usage(EXIT_SUCCESS);
124             case 'k':
125                 pgflags = (1 << KPF_KSM);
126                 pgflags_mask = (1 << KPF_KSM);
127                 break;
128             case 'm':
129                 mapflags_mask = parse_mapflags(optarg);
130                 break;
131             case 'o':
132                 sort_order = SortOrder::BY_OOMADJ;
133                 break;
134             case 'p':
135                 sort_order = SortOrder::BY_PSS;
136                 break;
137             case 'P':
138                 lib_prefix = optarg;
139                 break;
140             case 'r':
141                 sort_order = SortOrder::BY_RSS;
142                 break;
143             case 'R':
144                 reverse_sort = true;
145                 break;
146             case 's':
147                 sort_order = SortOrder::BY_SWAP;
148                 break;
149             case 'u':
150                 sort_order = SortOrder::BY_USS;
151                 break;
152             case 'v':
153                 sort_order = SortOrder::BY_VSS;
154                 break;
155             default:
156                 usage(EXIT_FAILURE);
157         }
158     }
159 
160     std::set<pid_t> pids;
161     if (!::android::smapinfo::get_all_pids(&pids)) {
162         std::cerr << "Failed to get all pids." << std::endl;
163         exit(EXIT_FAILURE);
164     }
165 
166     bool success = ::android::smapinfo::run_librank(
167             pgflags, pgflags_mask, pids, lib_prefix, all_libs, excluded_libs, mapflags_mask, format,
168             sort_order, reverse_sort, nullptr, std::cout, std::cerr);
169     if (!success) {
170         exit(EXIT_FAILURE);
171     }
172     return 0;
173 }
174