• 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 "read_dex_file.h"
18 
19 #include <fcntl.h>
20 
21 #include <algorithm>
22 #include <iterator>
23 #include <string>
24 #include <utility>
25 #include <vector>
26 
27 #include <android-base/logging.h>
28 #include <android-base/mapped_file.h>
29 #include <android-base/unique_fd.h>
30 #include <art_api/dex_file_support.h>
31 
32 #include "utils.h"
33 
34 namespace simpleperf {
35 
ReadSymbols(const std::vector<uint64_t> & dex_file_offsets,const std::function<std::unique_ptr<art_api::dex::DexFile> (uint64_t offset)> & open_file_cb,const std::function<void (DexFileSymbol *)> & symbol_cb)36 static bool ReadSymbols(
37     const std::vector<uint64_t>& dex_file_offsets,
38     const std::function<std::unique_ptr<art_api::dex::DexFile>(uint64_t offset)>& open_file_cb,
39     const std::function<void(DexFileSymbol*)>& symbol_cb) {
40   for (uint64_t dex_offset : dex_file_offsets) {
41     std::unique_ptr<art_api::dex::DexFile> dex_file = open_file_cb(dex_offset);
42     if (dex_file == nullptr) {
43       return false;
44     }
45 
46     auto callback = [&](const art_api::dex::DexFile::Method& method) {
47       size_t name_size, code_size;
48       const char* name = method.GetQualifiedName(/*with_params=*/false, &name_size);
49       size_t offset = method.GetCodeOffset(&code_size);
50       DexFileSymbol symbol{std::string_view(name, name_size), dex_offset + offset, code_size};
51       symbol_cb(&symbol);
52     };
53     dex_file->ForEachMethod(callback);
54   }
55 
56   return true;
57 }
58 
ReadSymbolsFromDexFileInMemory(void * addr,uint64_t size,const std::vector<uint64_t> & dex_file_offsets,const std::function<void (DexFileSymbol *)> & symbol_callback)59 bool ReadSymbolsFromDexFileInMemory(void* addr, uint64_t size,
60                                     const std::vector<uint64_t>& dex_file_offsets,
61                                     const std::function<void(DexFileSymbol*)>& symbol_callback) {
62   return ReadSymbols(
63       dex_file_offsets,
64       [&](uint64_t offset) -> std::unique_ptr<art_api::dex::DexFile> {
65         size_t max_file_size;
66         if (__builtin_sub_overflow(size, offset, &max_file_size)) {
67           return nullptr;
68         }
69         uint8_t* file_addr = static_cast<uint8_t*>(addr) + offset;
70         std::unique_ptr<art_api::dex::DexFile> dex_file;
71         art_api::dex::DexFile::Error error_msg =
72           art_api::dex::DexFile::Create(file_addr, max_file_size, nullptr, "", &dex_file);
73         if (dex_file == nullptr) {
74           LOG(WARNING) << "Failed to read dex file symbols: " << error_msg.ToString();
75           return nullptr;
76         }
77         return dex_file;
78       },
79       symbol_callback);
80 }
81 
ReadSymbolsFromDexFile(const std::string & file_path,const std::vector<uint64_t> & dex_file_offsets,const std::function<void (DexFileSymbol *)> & symbol_callback)82 bool ReadSymbolsFromDexFile(const std::string& file_path,
83                             const std::vector<uint64_t>& dex_file_offsets,
84                             const std::function<void(DexFileSymbol*)>& symbol_callback) {
85   android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file_path.c_str(), O_RDONLY | O_CLOEXEC)));
86   if (fd == -1) {
87     return false;
88   }
89   size_t file_size = GetFileSize(file_path);
90   if (file_size == 0) {
91     return false;
92   }
93   std::unique_ptr<android::base::MappedFile> map;
94   map = android::base::MappedFile::FromFd(fd, 0, file_size, PROT_READ);
95   if (map == nullptr) {
96     return false;
97   }
98   return ReadSymbolsFromDexFileInMemory(map->data(), file_size, dex_file_offsets, symbol_callback);
99 }
100 
101 }  // namespace simpleperf
102