blob: e83f98ee6bff10e178ca6073cb854490b8cae883 [file] [log] [blame]
David Sehrbeca4fe2017-03-30 17:50:24 -07001/*
2 * Copyright (C) 2017 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 <errno.h>
David Sehr55232f12017-04-19 14:06:49 -070018#include <inttypes.h>
David Sehrbeca4fe2017-03-30 17:50:24 -070019#include <stdint.h>
20#include <stdlib.h>
21#include <string.h>
22
23#include <iostream>
24#include <memory>
David Sehr3f3ec672017-04-05 14:43:38 -070025#include <vector>
David Sehrbeca4fe2017-03-30 17:50:24 -070026
27#include "android-base/stringprintf.h"
28
David Sehr3f3ec672017-04-05 14:43:38 -070029#include "base/stringpiece.h"
30
David Sehrbeca4fe2017-03-30 17:50:24 -070031#include "dex_file.h"
32#include "dex_ir.h"
33#include "dex_ir_builder.h"
David Sehr55232f12017-04-19 14:06:49 -070034#ifdef ART_TARGET_ANDROID
David Sehrbeca4fe2017-03-30 17:50:24 -070035#include "pagemap/pagemap.h"
David Sehr55232f12017-04-19 14:06:49 -070036#endif
David Sehrbeca4fe2017-03-30 17:50:24 -070037#include "runtime.h"
38#include "vdex_file.h"
39
40namespace art {
41
42using android::base::StringPrintf;
43
David Sehrbeca4fe2017-03-30 17:50:24 -070044static bool g_verbose = false;
David Sehr3f3ec672017-04-05 14:43:38 -070045
46// The width needed to print a file page offset (32-bit).
47static constexpr int kPageCountWidth =
48 static_cast<int>(std::numeric_limits<uint32_t>::digits10);
49// Display the sections.
50static constexpr char kSectionHeader[] = "Section name";
David Sehrbeca4fe2017-03-30 17:50:24 -070051
52struct DexSectionInfo {
53 public:
54 std::string name;
55 char letter;
56};
57
58static const std::map<uint16_t, DexSectionInfo> kDexSectionInfoMap = {
59 { DexFile::kDexTypeHeaderItem, { "Header", 'H' } },
60 { DexFile::kDexTypeStringIdItem, { "StringId", 'S' } },
61 { DexFile::kDexTypeTypeIdItem, { "TypeId", 'T' } },
62 { DexFile::kDexTypeProtoIdItem, { "ProtoId", 'P' } },
63 { DexFile::kDexTypeFieldIdItem, { "FieldId", 'F' } },
64 { DexFile::kDexTypeMethodIdItem, { "MethodId", 'M' } },
65 { DexFile::kDexTypeClassDefItem, { "ClassDef", 'C' } },
66 { DexFile::kDexTypeCallSiteIdItem, { "CallSiteId", 'z' } },
67 { DexFile::kDexTypeMethodHandleItem, { "MethodHandle", 'Z' } },
68 { DexFile::kDexTypeMapList, { "TypeMap", 'L' } },
69 { DexFile::kDexTypeTypeList, { "TypeList", 't' } },
70 { DexFile::kDexTypeAnnotationSetRefList, { "AnnotationSetReferenceItem", '1' } },
71 { DexFile::kDexTypeAnnotationSetItem, { "AnnotationSetItem", '2' } },
72 { DexFile::kDexTypeClassDataItem, { "ClassData", 'c' } },
73 { DexFile::kDexTypeCodeItem, { "CodeItem", 'X' } },
74 { DexFile::kDexTypeStringDataItem, { "StringData", 's' } },
75 { DexFile::kDexTypeDebugInfoItem, { "DebugInfo", 'D' } },
76 { DexFile::kDexTypeAnnotationItem, { "AnnotationItem", '3' } },
77 { DexFile::kDexTypeEncodedArrayItem, { "EncodedArrayItem", 'E' } },
78 { DexFile::kDexTypeAnnotationsDirectoryItem, { "AnnotationsDirectoryItem", '4' } }
79};
80
81class PageCount {
82 public:
83 PageCount() {
84 for (auto it = kDexSectionInfoMap.begin(); it != kDexSectionInfoMap.end(); ++it) {
85 map_[it->first] = 0;
86 }
87 }
88 void Increment(uint16_t type) {
89 map_[type]++;
90 }
91 size_t Get(uint16_t type) const {
92 return map_.at(type);
93 }
94 private:
95 std::map<uint16_t, size_t> map_;
96 DISALLOW_COPY_AND_ASSIGN(PageCount);
97};
98
David Sehr3f3ec672017-04-05 14:43:38 -070099class Printer {
100 public:
101 Printer() : section_header_width_(ComputeHeaderWidth()) {
David Sehrbeca4fe2017-03-30 17:50:24 -0700102 }
David Sehr3f3ec672017-04-05 14:43:38 -0700103
104 void PrintHeader() const {
105 std::cout << StringPrintf("%-*s %*s %*s %% of %% of",
106 section_header_width_,
107 kSectionHeader,
108 kPageCountWidth,
109 "resident",
110 kPageCountWidth,
111 "total"
112 )
113 << std::endl;
114 std::cout << StringPrintf("%-*s %*s %*s sect. total",
115 section_header_width_,
116 "",
117 kPageCountWidth,
118 "pages",
119 kPageCountWidth,
120 "pages")
121 << std::endl;
122 }
123
124 void PrintOne(const char* name,
125 size_t resident,
126 size_t mapped,
127 double percent_of_section,
128 double percent_of_total) const {
129 // 6.2 is sufficient to print 0-100% with two decimal places of accuracy.
130 std::cout << StringPrintf("%-*s %*zd %*zd %6.2f %6.2f",
131 section_header_width_,
132 name,
133 kPageCountWidth,
134 resident,
135 kPageCountWidth,
136 mapped,
137 percent_of_section,
138 percent_of_total)
139 << std::endl;
140 }
141
142 void PrintSkipLine() const { std::cout << std::endl; }
143
144 // Computes the width of the section header column in the table (for fixed formatting).
145 static int ComputeHeaderWidth() {
146 int header_width = 0;
147 for (const auto& pair : kDexSectionInfoMap) {
148 const DexSectionInfo& section_info = pair.second;
149 header_width = std::max(header_width, static_cast<int>(section_info.name.length()));
150 }
151 return header_width;
152 }
153
154 private:
155 const int section_header_width_;
156};
157
158static void PrintLetterKey() {
159 std::cout << "L pagetype" << std::endl;
160 for (const auto& pair : kDexSectionInfoMap) {
161 const DexSectionInfo& section_info = pair.second;
162 std::cout << section_info.letter << " " << section_info.name.c_str() << std::endl;
163 }
164 std::cout << "* (Executable page resident)" << std::endl;
165 std::cout << ". (Mapped page not resident)" << std::endl;
David Sehrbeca4fe2017-03-30 17:50:24 -0700166}
167
David Sehr55232f12017-04-19 14:06:49 -0700168#ifdef ART_TARGET_ANDROID
David Sehrbeca4fe2017-03-30 17:50:24 -0700169static char PageTypeChar(uint16_t type) {
170 if (kDexSectionInfoMap.find(type) == kDexSectionInfoMap.end()) {
171 return '-';
172 }
173 return kDexSectionInfoMap.find(type)->second.letter;
174}
175
176static uint16_t FindSectionTypeForPage(size_t page,
177 const std::vector<dex_ir::DexFileSection>& sections) {
178 for (const auto& section : sections) {
179 size_t first_page_of_section = section.offset / kPageSize;
180 // Only consider non-empty sections.
181 if (section.size == 0) {
182 continue;
183 }
184 // Attribute the page to the highest-offset section that starts before the page.
185 if (first_page_of_section <= page) {
186 return section.type;
187 }
188 }
189 // If there's no non-zero sized section with an offset below offset we're looking for, it
190 // must be the header.
191 return DexFile::kDexTypeHeaderItem;
192}
193
194static void ProcessPageMap(uint64_t* pagemap,
195 size_t start,
196 size_t end,
197 const std::vector<dex_ir::DexFileSection>& sections,
198 PageCount* page_counts) {
David Sehr55232f12017-04-19 14:06:49 -0700199 static constexpr size_t kLineLength = 32;
David Sehrbeca4fe2017-03-30 17:50:24 -0700200 for (size_t page = start; page < end; ++page) {
201 char type_char = '.';
202 if (PM_PAGEMAP_PRESENT(pagemap[page])) {
David Sehr093a6fb2017-05-09 15:41:09 -0700203 const size_t dex_page_offset = page - start;
204 uint16_t type = FindSectionTypeForPage(dex_page_offset, sections);
David Sehrbeca4fe2017-03-30 17:50:24 -0700205 page_counts->Increment(type);
206 type_char = PageTypeChar(type);
207 }
208 if (g_verbose) {
209 std::cout << type_char;
210 if ((page - start) % kLineLength == kLineLength - 1) {
211 std::cout << std::endl;
212 }
213 }
214 }
215 if (g_verbose) {
216 if ((end - start) % kLineLength != 0) {
217 std::cout << std::endl;
218 }
219 }
220}
221
222static void DisplayDexStatistics(size_t start,
223 size_t end,
224 const PageCount& resident_pages,
David Sehr3f3ec672017-04-05 14:43:38 -0700225 const std::vector<dex_ir::DexFileSection>& sections,
226 Printer* printer) {
David Sehrbeca4fe2017-03-30 17:50:24 -0700227 // Compute the total possible sizes for sections.
228 PageCount mapped_pages;
229 DCHECK_GE(end, start);
230 size_t total_mapped_pages = end - start;
231 if (total_mapped_pages == 0) {
232 return;
233 }
234 for (size_t page = start; page < end; ++page) {
David Sehr093a6fb2017-05-09 15:41:09 -0700235 const size_t dex_page_offset = page - start;
236 mapped_pages.Increment(FindSectionTypeForPage(dex_page_offset, sections));
David Sehrbeca4fe2017-03-30 17:50:24 -0700237 }
238 size_t total_resident_pages = 0;
David Sehr3f3ec672017-04-05 14:43:38 -0700239 printer->PrintHeader();
David Sehrbeca4fe2017-03-30 17:50:24 -0700240 for (size_t i = sections.size(); i > 0; --i) {
241 const dex_ir::DexFileSection& section = sections[i - 1];
242 const uint16_t type = section.type;
243 const DexSectionInfo& section_info = kDexSectionInfoMap.find(type)->second;
244 size_t pages_resident = resident_pages.Get(type);
245 double percent_resident = 0;
246 if (mapped_pages.Get(type) > 0) {
247 percent_resident = 100.0 * pages_resident / mapped_pages.Get(type);
248 }
David Sehr3f3ec672017-04-05 14:43:38 -0700249 printer->PrintOne(section_info.name.c_str(),
250 pages_resident,
251 mapped_pages.Get(type),
252 percent_resident,
253 100.0 * pages_resident / total_mapped_pages);
David Sehrbeca4fe2017-03-30 17:50:24 -0700254 total_resident_pages += pages_resident;
255 }
David Sehr3f3ec672017-04-05 14:43:38 -0700256 double percent_of_total = 100.0 * total_resident_pages / total_mapped_pages;
257 printer->PrintOne("GRAND TOTAL",
258 total_resident_pages,
259 total_mapped_pages,
260 percent_of_total,
261 percent_of_total);
262 printer->PrintSkipLine();
David Sehrbeca4fe2017-03-30 17:50:24 -0700263}
264
265static void ProcessOneDexMapping(uint64_t* pagemap,
266 uint64_t map_start,
267 const DexFile* dex_file,
David Sehr3f3ec672017-04-05 14:43:38 -0700268 uint64_t vdex_start,
269 Printer* printer) {
David Sehrbeca4fe2017-03-30 17:50:24 -0700270 uint64_t dex_file_start = reinterpret_cast<uint64_t>(dex_file->Begin());
271 size_t dex_file_size = dex_file->Size();
272 if (dex_file_start < vdex_start) {
273 std::cerr << "Dex file start offset for "
274 << dex_file->GetLocation().c_str()
275 << " is incorrect: map start "
David Sehr55232f12017-04-19 14:06:49 -0700276 << StringPrintf("%" PRIx64 " > dex start %" PRIx64 "\n", map_start, dex_file_start)
David Sehrbeca4fe2017-03-30 17:50:24 -0700277 << std::endl;
278 return;
279 }
David Sehrc0e638f2017-04-07 16:56:46 -0700280 uint64_t start_page = (dex_file_start - vdex_start) / kPageSize;
281 uint64_t start_address = start_page * kPageSize;
282 uint64_t end_page = RoundUp(start_address + dex_file_size, kPageSize) / kPageSize;
David Sehrbeca4fe2017-03-30 17:50:24 -0700283 std::cout << "DEX "
284 << dex_file->GetLocation().c_str()
David Sehr55232f12017-04-19 14:06:49 -0700285 << StringPrintf(": %" PRIx64 "-%" PRIx64,
David Sehrc0e638f2017-04-07 16:56:46 -0700286 map_start + start_page * kPageSize,
287 map_start + end_page * kPageSize)
David Sehrbeca4fe2017-03-30 17:50:24 -0700288 << std::endl;
289 // Build a list of the dex file section types, sorted from highest offset to lowest.
290 std::vector<dex_ir::DexFileSection> sections;
291 {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800292 std::unique_ptr<dex_ir::Header> header(dex_ir::DexIrBuilder(*dex_file,
293 /*eagerly_assign_offsets*/ true));
David Sehrbeca4fe2017-03-30 17:50:24 -0700294 sections = dex_ir::GetSortedDexFileSections(header.get(),
295 dex_ir::SortDirection::kSortDescending);
296 }
297 PageCount section_resident_pages;
David Sehrc0e638f2017-04-07 16:56:46 -0700298 ProcessPageMap(pagemap, start_page, end_page, sections, &section_resident_pages);
David Sehr3f3ec672017-04-05 14:43:38 -0700299 DisplayDexStatistics(start_page, end_page, section_resident_pages, sections, printer);
David Sehrbeca4fe2017-03-30 17:50:24 -0700300}
301
David Sehr592f8022017-05-04 13:58:29 -0700302static bool IsVdexFileMapping(const std::string& mapped_name) {
David Sehrbeca4fe2017-03-30 17:50:24 -0700303 // Confirm that the map is from a vdex file.
304 static const char* suffixes[] = { ".vdex" };
David Sehr592f8022017-05-04 13:58:29 -0700305 for (const char* suffix : suffixes) {
306 size_t match_loc = mapped_name.find(suffix);
307 if (match_loc != std::string::npos && mapped_name.length() == match_loc + strlen(suffix)) {
308 return true;
David Sehrbeca4fe2017-03-30 17:50:24 -0700309 }
310 }
David Sehr592f8022017-05-04 13:58:29 -0700311 return false;
312}
313
314static bool DisplayMappingIfFromVdexFile(pm_map_t* map, Printer* printer) {
315 std::string vdex_name = pm_map_name(map);
David Sehrbeca4fe2017-03-30 17:50:24 -0700316 // Extract all the dex files from the vdex file.
317 std::string error_msg;
318 std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_name,
319 false /*writeable*/,
320 false /*low_4gb*/,
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +0100321 false /*unquicken */,
David Sehrbeca4fe2017-03-30 17:50:24 -0700322 &error_msg /*out*/));
323 if (vdex == nullptr) {
324 std::cerr << "Could not open vdex file "
David Sehr3f3ec672017-04-05 14:43:38 -0700325 << vdex_name
David Sehrbeca4fe2017-03-30 17:50:24 -0700326 << ": error "
David Sehr3f3ec672017-04-05 14:43:38 -0700327 << error_msg
David Sehrbeca4fe2017-03-30 17:50:24 -0700328 << std::endl;
329 return false;
330 }
331
332 std::vector<std::unique_ptr<const DexFile>> dex_files;
333 if (!vdex->OpenAllDexFiles(&dex_files, &error_msg)) {
334 std::cerr << "Dex files could not be opened for "
David Sehr3f3ec672017-04-05 14:43:38 -0700335 << vdex_name
David Sehrbeca4fe2017-03-30 17:50:24 -0700336 << ": error "
David Sehr3f3ec672017-04-05 14:43:38 -0700337 << error_msg
David Sehrbeca4fe2017-03-30 17:50:24 -0700338 << std::endl;
David Sehr592f8022017-05-04 13:58:29 -0700339 return false;
David Sehrbeca4fe2017-03-30 17:50:24 -0700340 }
341 // Open the page mapping (one uint64_t per page) for the entire vdex mapping.
342 uint64_t* pagemap;
343 size_t len;
344 if (pm_map_pagemap(map, &pagemap, &len) != 0) {
345 std::cerr << "Error creating pagemap." << std::endl;
346 return false;
347 }
348 // Process the dex files.
349 std::cout << "MAPPING "
350 << pm_map_name(map)
David Sehr55232f12017-04-19 14:06:49 -0700351 << StringPrintf(": %" PRIx64 "-%" PRIx64, pm_map_start(map), pm_map_end(map))
David Sehrbeca4fe2017-03-30 17:50:24 -0700352 << std::endl;
353 for (const auto& dex_file : dex_files) {
354 ProcessOneDexMapping(pagemap,
355 pm_map_start(map),
356 dex_file.get(),
David Sehr3f3ec672017-04-05 14:43:38 -0700357 reinterpret_cast<uint64_t>(vdex->Begin()),
358 printer);
David Sehrbeca4fe2017-03-30 17:50:24 -0700359 }
360 free(pagemap);
361 return true;
362}
363
David Sehr3f3ec672017-04-05 14:43:38 -0700364static void ProcessOneOatMapping(uint64_t* pagemap, size_t size, Printer* printer) {
David Sehr55232f12017-04-19 14:06:49 -0700365 static constexpr size_t kLineLength = 32;
David Sehr3f3ec672017-04-05 14:43:38 -0700366 size_t resident_page_count = 0;
367 for (size_t page = 0; page < size; ++page) {
368 char type_char = '.';
369 if (PM_PAGEMAP_PRESENT(pagemap[page])) {
370 ++resident_page_count;
371 type_char = '*';
372 }
373 if (g_verbose) {
374 std::cout << type_char;
375 if (page % kLineLength == kLineLength - 1) {
376 std::cout << std::endl;
377 }
378 }
379 }
380 if (g_verbose) {
381 if (size % kLineLength != 0) {
382 std::cout << std::endl;
383 }
384 }
385 double percent_of_total = 100.0 * resident_page_count / size;
386 printer->PrintHeader();
387 printer->PrintOne("EXECUTABLE", resident_page_count, size, percent_of_total, percent_of_total);
388 printer->PrintSkipLine();
389}
390
David Sehr592f8022017-05-04 13:58:29 -0700391static bool IsOatFileMapping(const std::string& mapped_name) {
392 // Confirm that the map is from an oat file.
David Sehr3f3ec672017-04-05 14:43:38 -0700393 static const char* suffixes[] = { ".odex", ".oat" };
David Sehr592f8022017-05-04 13:58:29 -0700394 for (const char* suffix : suffixes) {
395 size_t match_loc = mapped_name.find(suffix);
396 if (match_loc != std::string::npos && mapped_name.length() == match_loc + strlen(suffix)) {
397 return true;
David Sehr3f3ec672017-04-05 14:43:38 -0700398 }
399 }
David Sehr592f8022017-05-04 13:58:29 -0700400 return false;
401}
402
403static bool DisplayMappingIfFromOatFile(pm_map_t* map, Printer* printer) {
David Sehr3f3ec672017-04-05 14:43:38 -0700404 // Open the page mapping (one uint64_t per page) for the entire vdex mapping.
405 uint64_t* pagemap;
406 size_t len;
407 if (pm_map_pagemap(map, &pagemap, &len) != 0) {
408 std::cerr << "Error creating pagemap." << std::endl;
409 return false;
410 }
411 // Process the dex files.
412 std::cout << "MAPPING "
413 << pm_map_name(map)
David Sehr55232f12017-04-19 14:06:49 -0700414 << StringPrintf(": %" PRIx64 "-%" PRIx64, pm_map_start(map), pm_map_end(map))
David Sehr3f3ec672017-04-05 14:43:38 -0700415 << std::endl;
416 ProcessOneOatMapping(pagemap, len, printer);
417 free(pagemap);
418 return true;
419}
420
421static bool FilterByNameContains(const std::string& mapped_file_name,
422 const std::vector<std::string>& name_filters) {
423 // If no filters were set, everything matches.
424 if (name_filters.empty()) {
425 return true;
426 }
427 for (const auto& name_contains : name_filters) {
428 if (mapped_file_name.find(name_contains) != std::string::npos) {
429 return true;
430 }
431 }
432 return false;
433}
David Sehr55232f12017-04-19 14:06:49 -0700434#endif
David Sehrbeca4fe2017-03-30 17:50:24 -0700435
436static void Usage(const char* cmd) {
David Sehr55232f12017-04-19 14:06:49 -0700437 std::cout << "Usage: " << cmd << " [options] pid" << std::endl
David Sehr3f3ec672017-04-05 14:43:38 -0700438 << " --contains=<string>: Display sections containing string." << std::endl
439 << " --help: Shows this message." << std::endl
440 << " --verbose: Makes displays verbose." << std::endl;
441 PrintLetterKey();
David Sehrbeca4fe2017-03-30 17:50:24 -0700442}
443
444static int DexDiagMain(int argc, char* argv[]) {
445 if (argc < 2) {
446 Usage(argv[0]);
447 return EXIT_FAILURE;
448 }
449
David Sehr3f3ec672017-04-05 14:43:38 -0700450 std::vector<std::string> name_filters;
David Sehrbeca4fe2017-03-30 17:50:24 -0700451 // TODO: add option to track usage by class name, etc.
452 for (int i = 1; i < argc - 1; ++i) {
David Sehr3f3ec672017-04-05 14:43:38 -0700453 const StringPiece option(argv[i]);
454 if (option == "--help") {
455 Usage(argv[0]);
456 return EXIT_SUCCESS;
457 } else if (option == "--verbose") {
David Sehrbeca4fe2017-03-30 17:50:24 -0700458 g_verbose = true;
David Sehr3f3ec672017-04-05 14:43:38 -0700459 } else if (option.starts_with("--contains=")) {
460 std::string contains(option.substr(strlen("--contains=")).data());
461 name_filters.push_back(contains);
David Sehrbeca4fe2017-03-30 17:50:24 -0700462 } else {
463 Usage(argv[0]);
464 return EXIT_FAILURE;
465 }
466 }
467
468 // Art specific set up.
Andreas Gampe51d80cc2017-06-21 21:05:13 -0700469 InitLogging(argv, Runtime::Abort);
David Sehrbeca4fe2017-03-30 17:50:24 -0700470 MemMap::Init();
471
David Sehr55232f12017-04-19 14:06:49 -0700472#ifdef ART_TARGET_ANDROID
David Sehrbeca4fe2017-03-30 17:50:24 -0700473 pid_t pid;
474 char* endptr;
475 pid = (pid_t)strtol(argv[argc - 1], &endptr, 10);
476 if (*endptr != '\0' || kill(pid, 0) != 0) {
477 std::cerr << StringPrintf("Invalid PID \"%s\".\n", argv[argc - 1]) << std::endl;
478 return EXIT_FAILURE;
479 }
480
481 // get libpagemap kernel information.
482 pm_kernel_t* ker;
483 if (pm_kernel_create(&ker) != 0) {
484 std::cerr << "Error creating kernel interface -- does this kernel have pagemap?" << std::endl;
485 return EXIT_FAILURE;
486 }
487
488 // get libpagemap process information.
489 pm_process_t* proc;
490 if (pm_process_create(ker, pid, &proc) != 0) {
491 std::cerr << "Error creating process interface -- does process "
492 << pid
493 << " really exist?"
494 << std::endl;
495 return EXIT_FAILURE;
496 }
497
498 // Get the set of mappings by the specified process.
499 pm_map_t** maps;
500 size_t num_maps;
501 if (pm_process_maps(proc, &maps, &num_maps) != 0) {
502 std::cerr << "Error listing maps." << std::endl;
503 return EXIT_FAILURE;
504 }
505
David Sehr55232f12017-04-19 14:06:49 -0700506 bool match_found = false;
507 // Process the mappings that are due to vdex or oat files.
David Sehr3f3ec672017-04-05 14:43:38 -0700508 Printer printer;
David Sehrbeca4fe2017-03-30 17:50:24 -0700509 for (size_t i = 0; i < num_maps; ++i) {
David Sehr3f3ec672017-04-05 14:43:38 -0700510 std::string mapped_file_name = pm_map_name(maps[i]);
511 // Filter by name contains options (if any).
512 if (!FilterByNameContains(mapped_file_name, name_filters)) {
513 continue;
514 }
David Sehr592f8022017-05-04 13:58:29 -0700515 if (IsVdexFileMapping(mapped_file_name)) {
516 if (!DisplayMappingIfFromVdexFile(maps[i], &printer)) {
517 return EXIT_FAILURE;
518 }
519 match_found = true;
520 } else if (IsOatFileMapping(mapped_file_name)) {
521 if (!DisplayMappingIfFromOatFile(maps[i], &printer)) {
522 return EXIT_FAILURE;
523 }
524 match_found = true;
David Sehrbeca4fe2017-03-30 17:50:24 -0700525 }
526 }
David Sehr55232f12017-04-19 14:06:49 -0700527 if (!match_found) {
David Sehr592f8022017-05-04 13:58:29 -0700528 std::cerr << "No relevant memory maps were found." << std::endl;
David Sehr55232f12017-04-19 14:06:49 -0700529 return EXIT_FAILURE;
530 }
531#endif
David Sehrbeca4fe2017-03-30 17:50:24 -0700532
David Sehr3f3ec672017-04-05 14:43:38 -0700533 return EXIT_SUCCESS;
David Sehrbeca4fe2017-03-30 17:50:24 -0700534}
535
536} // namespace art
537
538int main(int argc, char* argv[]) {
539 return art::DexDiagMain(argc, argv);
540}