/* * Copyright (C) 2019 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 "profile_boot_info.h" #include #include #include "dex/dex_file.h" #include "profile_helpers.h" namespace art { void ProfileBootInfo::Add(const DexFile* dex_file, uint32_t method_index) { auto it = std::find(dex_files_.begin(), dex_files_.end(), dex_file); uint32_t index = 0; if (it == dex_files_.end()) { index = dex_files_.size(); dex_files_.push_back(dex_file); } else { index = std::distance(dex_files_.begin(), it); } methods_.push_back(std::make_pair(index, method_index)); } bool ProfileBootInfo::Save(int fd) const { std::vector buffer; // Store dex file locations. for (const DexFile* dex_file : dex_files_) { AddUintToBuffer(&buffer, static_cast(dex_file->GetLocation().size())); AddStringToBuffer(&buffer, dex_file->GetLocation()); } // Store marker between dex file locations and methods. AddUintToBuffer(&buffer, static_cast(0)); // Store pairs of , in compilation order. for (const std::pair& pair : methods_) { AddUintToBuffer(&buffer, pair.first); AddUintToBuffer(&buffer, pair.second); } if (!WriteBuffer(fd, buffer.data(), buffer.size())) { return false; } return true; } bool ProfileBootInfo::Load(int fd, const std::vector& dex_files) { // Read dex file locations. do { uint8_t string_length; int bytes_read = TEMP_FAILURE_RETRY(read(fd, &string_length, sizeof(uint8_t))); if (bytes_read < 0) { PLOG(ERROR) << "Unexpected error reading profile"; return false; } else if (bytes_read == 0) { if (dex_files.empty()) { // If no dex files have been passed, that's expected. return true; } else { LOG(ERROR) << "Unexpected end of file for length"; return false; } } if (string_length == 0) { break; } std::unique_ptr data(new char[string_length]); bytes_read = TEMP_FAILURE_RETRY(read(fd, data.get(), string_length)); if (bytes_read < 0) { PLOG(WARNING) << "Unexpected error reading profile"; return false; } else if (bytes_read == 0) { LOG(ERROR) << "Unexpected end of file for name"; return false; } // Map the location to an instance of dex file in `dex_files`. auto it = std::find_if(dex_files.begin(), dex_files.end(), [string_length, &data](const DexFile* file) { std::string dex_location = file->GetLocation(); return dex_location.size() == string_length && (strncmp(data.get(), dex_location.data(), string_length) == 0); }); if (it != dex_files.end()) { dex_files_.push_back(*it); } else { LOG(ERROR) << "Couldn't find " << std::string(data.get(), string_length); return false; } } while (true); // Read methods. do { uint32_t dex_file_index; uint32_t method_id; int bytes_read = TEMP_FAILURE_RETRY(read(fd, &dex_file_index, sizeof(dex_file_index))); if (bytes_read <= 0) { break; } bytes_read = TEMP_FAILURE_RETRY(read(fd, &method_id, sizeof(method_id))); if (bytes_read <= 0) { LOG(ERROR) << "Didn't get a method id"; return false; } methods_.push_back(std::make_pair(dex_file_index, method_id)); } while (true); return true; } } // namespace art