/* * 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; }); }