| /* |
| * Copyright (C) 2016 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 "multi_oat_relative_patcher.h" |
| |
| #include <android-base/logging.h> |
| |
| #include "base/bit_utils.h" |
| #include "base/globals.h" |
| #include "driver/compiled_method_storage.h" |
| |
| namespace art { |
| namespace linker { |
| |
| void MultiOatRelativePatcher::ThunkProvider::GetThunkCode(const LinkerPatch& patch, |
| /*out*/ ArrayRef<const uint8_t>* code, |
| /*out*/ std::string* debug_name) { |
| *code = storage_->GetThunkCode(patch, debug_name); |
| DCHECK(!code->empty()); |
| } |
| |
| |
| MultiOatRelativePatcher::MultiOatRelativePatcher(InstructionSet instruction_set, |
| const InstructionSetFeatures* features, |
| CompiledMethodStorage* storage) |
| : thunk_provider_(storage), |
| method_offset_map_(), |
| relative_patcher_(RelativePatcher::Create(instruction_set, |
| features, |
| &thunk_provider_, |
| &method_offset_map_)), |
| adjustment_(0u), |
| instruction_set_(instruction_set), |
| start_size_code_alignment_(0u), |
| start_size_relative_call_thunks_(0u), |
| start_size_misc_thunks_(0u) { |
| } |
| |
| void MultiOatRelativePatcher::StartOatFile(uint32_t adjustment) { |
| DCHECK_ALIGNED(adjustment, kElfSegmentAlignment); |
| adjustment_ = adjustment; |
| |
| start_size_code_alignment_ = relative_patcher_->CodeAlignmentSize(); |
| start_size_relative_call_thunks_ = relative_patcher_->RelativeCallThunksSize(); |
| start_size_misc_thunks_ = relative_patcher_->MiscThunksSize(); |
| } |
| |
| uint32_t MultiOatRelativePatcher::CodeAlignmentSize() const { |
| DCHECK_GE(relative_patcher_->CodeAlignmentSize(), start_size_code_alignment_); |
| return relative_patcher_->CodeAlignmentSize() - start_size_code_alignment_; |
| } |
| |
| uint32_t MultiOatRelativePatcher::RelativeCallThunksSize() const { |
| DCHECK_GE(relative_patcher_->RelativeCallThunksSize(), start_size_relative_call_thunks_); |
| return relative_patcher_->RelativeCallThunksSize() - start_size_relative_call_thunks_; |
| } |
| |
| uint32_t MultiOatRelativePatcher::MiscThunksSize() const { |
| DCHECK_GE(relative_patcher_->MiscThunksSize(), start_size_misc_thunks_); |
| return relative_patcher_->MiscThunksSize() - start_size_misc_thunks_; |
| } |
| |
| std::pair<bool, uint32_t> MultiOatRelativePatcher::MethodOffsetMap::FindMethodOffset( |
| MethodReference ref) { |
| auto it = map.find(ref); |
| if (it == map.end()) { |
| return std::pair<bool, uint32_t>(false, 0u); |
| } else { |
| return std::pair<bool, uint32_t>(true, it->second); |
| } |
| } |
| } // namespace linker |
| } // namespace art |