| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "read_dex_file.h" |
| |
| #include <fcntl.h> |
| |
| #include <algorithm> |
| #include <iterator> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include <android-base/logging.h> |
| #include <android-base/unique_fd.h> |
| #include <art_api/dex_file_support.h> |
| |
| static bool ReadSymbols( |
| const std::vector<uint64_t>& dex_file_offsets, std::vector<DexFileSymbol>* symbols, |
| const std::function<std::unique_ptr<art_api::dex::DexFile>(uint64_t offset)>& open_file_cb) { |
| for (uint64_t offset : dex_file_offsets) { |
| std::unique_ptr<art_api::dex::DexFile> dex_file = open_file_cb(offset); |
| if (dex_file == nullptr) { |
| return false; |
| } |
| |
| std::vector<art_api::dex::MethodInfo> file_syms = dex_file->GetAllMethodInfos(false); |
| |
| // Adjust offsets to be from the start of the combined file. |
| for (art_api::dex::MethodInfo& sym : file_syms) { |
| sym.offset += offset; |
| } |
| |
| if (symbols->empty()) { |
| *symbols = std::move(file_syms); |
| } else { |
| symbols->reserve(symbols->size() + file_syms.size()); |
| std::move(std::begin(file_syms), std::end(file_syms), std::back_inserter(*symbols)); |
| } |
| } |
| |
| return true; |
| } |
| |
| bool ReadSymbolsFromDexFileInMemory(void* addr, uint64_t size, |
| const std::vector<uint64_t>& dex_file_offsets, |
| std::vector<DexFileSymbol>* symbols) { |
| return ReadSymbols( |
| dex_file_offsets, symbols, [&](uint64_t offset) -> std::unique_ptr<art_api::dex::DexFile> { |
| size_t max_file_size; |
| if (__builtin_sub_overflow(size, offset, &max_file_size)) { |
| return nullptr; |
| } |
| uint8_t* file_addr = static_cast<uint8_t*>(addr) + offset; |
| std::string error_msg; |
| std::unique_ptr<art_api::dex::DexFile> dex_file = |
| art_api::dex::DexFile::OpenFromMemory(file_addr, &max_file_size, "", &error_msg); |
| if (dex_file == nullptr) { |
| LOG(WARNING) << "Failed to read dex file symbols: " << error_msg; |
| return nullptr; |
| } |
| return dex_file; |
| }); |
| } |
| |
| bool ReadSymbolsFromDexFile(const std::string& file_path, |
| const std::vector<uint64_t>& dex_file_offsets, |
| std::vector<DexFileSymbol>* symbols) { |
| android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file_path.c_str(), O_RDONLY | O_CLOEXEC))); |
| if (fd == -1) { |
| return false; |
| } |
| return ReadSymbols( |
| dex_file_offsets, symbols, [&](uint64_t offset) -> std::unique_ptr<art_api::dex::DexFile> { |
| std::string error_msg; |
| std::unique_ptr<art_api::dex::DexFile> dex_file = |
| art_api::dex::DexFile::OpenFromFd(fd, offset, file_path, &error_msg); |
| if (dex_file == nullptr) { |
| LOG(WARNING) << "Failed to read dex file symbols from '" << file_path |
| << "': " << error_msg; |
| return nullptr; |
| } |
| return dex_file; |
| }); |
| } |