1944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko/* 2944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko * Copyright (C) 2016 The Android Open Source Project 3944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko * 4944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko * Licensed under the Apache License, Version 2.0 (the "License"); 5944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko * you may not use this file except in compliance with the License. 6944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko * You may obtain a copy of the License at 7944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko * 8944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko * http://www.apache.org/licenses/LICENSE-2.0 9944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko * 10944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko * Unless required by applicable law or agreed to in writing, software 11944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko * distributed under the License is distributed on an "AS IS" BASIS, 12944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko * See the License for the specific language governing permissions and 14944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko * limitations under the License. 15944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko */ 16944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 17944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko#include "compiled_method.h" 18944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko#include "gtest/gtest.h" 19944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko#include "multi_oat_relative_patcher.h" 20944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko#include "vector_output_stream.h" 21944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 22944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Markonamespace art { 23944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Markonamespace linker { 24944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 25944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Markostatic const MethodReference kNullMethodRef = MethodReference(nullptr, 0u); 26944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 27944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Markostatic bool EqualRef(MethodReference lhs, MethodReference rhs) { 28944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko return lhs.dex_file == rhs.dex_file && lhs.dex_method_index == rhs.dex_method_index; 29944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko} 30944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 31944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Markoclass MultiOatRelativePatcherTest : public testing::Test { 32944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko protected: 33944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko class MockPatcher : public RelativePatcher { 34944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko public: 35944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko MockPatcher() { } 36944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 37944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t ReserveSpace(uint32_t offset, 38944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko const CompiledMethod* compiled_method ATTRIBUTE_UNUSED, 39944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko MethodReference method_ref) OVERRIDE { 40944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko last_reserve_offset_ = offset; 41944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko last_reserve_method_ = method_ref; 42944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko offset += next_reserve_adjustment_; 43944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko next_reserve_adjustment_ = 0u; 44944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko return offset; 45944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko } 46944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 47944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t ReserveSpaceEnd(uint32_t offset) OVERRIDE { 48944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko last_reserve_offset_ = offset; 49944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko last_reserve_method_ = kNullMethodRef; 50944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko offset += next_reserve_adjustment_; 51944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko next_reserve_adjustment_ = 0u; 52944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko return offset; 53944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko } 54944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 55944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t WriteThunks(OutputStream* out, uint32_t offset) OVERRIDE { 56944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko last_write_offset_ = offset; 57944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko if (next_write_alignment_ != 0u) { 58944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko offset += next_write_alignment_; 59944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko bool success = WriteCodeAlignment(out, next_write_alignment_); 60944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko CHECK(success); 61944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko next_write_alignment_ = 0u; 62944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko } 63944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko if (next_write_call_thunk_ != 0u) { 64944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko offset += next_write_call_thunk_; 65944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko std::vector<uint8_t> thunk(next_write_call_thunk_, 'c'); 66944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko bool success = WriteRelCallThunk(out, ArrayRef<const uint8_t>(thunk)); 67944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko CHECK(success); 68944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko next_write_call_thunk_ = 0u; 69944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko } 70944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko if (next_write_misc_thunk_ != 0u) { 71944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko offset += next_write_misc_thunk_; 72944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko std::vector<uint8_t> thunk(next_write_misc_thunk_, 'm'); 73944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko bool success = WriteMiscThunk(out, ArrayRef<const uint8_t>(thunk)); 74944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko CHECK(success); 75944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko next_write_misc_thunk_ = 0u; 76944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko } 77944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko return offset; 78944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko } 79944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 80944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko void PatchCall(std::vector<uint8_t>* code ATTRIBUTE_UNUSED, 81944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t literal_offset, 82944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t patch_offset, 83944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t target_offset) OVERRIDE { 84944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko last_literal_offset_ = literal_offset; 85944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko last_patch_offset_ = patch_offset; 86944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko last_target_offset_ = target_offset; 87944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko } 88944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 89cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko void PatchPcRelativeReference(std::vector<uint8_t>* code ATTRIBUTE_UNUSED, 90cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko const LinkerPatch& patch, 91cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko uint32_t patch_offset, 92cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko uint32_t target_offset) OVERRIDE { 93944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko last_literal_offset_ = patch.LiteralOffset(); 94944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko last_patch_offset_ = patch_offset; 95944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko last_target_offset_ = target_offset; 96944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko } 97944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 98944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t last_reserve_offset_ = 0u; 99944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko MethodReference last_reserve_method_ = kNullMethodRef; 100944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t next_reserve_adjustment_ = 0u; 101944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 102944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t last_write_offset_ = 0u; 103944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t next_write_alignment_ = 0u; 104944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t next_write_call_thunk_ = 0u; 105944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t next_write_misc_thunk_ = 0u; 106944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 107944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t last_literal_offset_ = 0u; 108944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t last_patch_offset_ = 0u; 109944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t last_target_offset_ = 0u; 110944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko }; 111944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 112944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko MultiOatRelativePatcherTest() 113944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko : instruction_set_features_(InstructionSetFeatures::FromCppDefines()), 114944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko patcher_(kRuntimeISA, instruction_set_features_.get()) { 115944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko std::unique_ptr<MockPatcher> mock(new MockPatcher()); 116944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko mock_ = mock.get(); 117944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko patcher_.relative_patcher_ = std::move(mock); 118944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko } 119944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 120944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko std::unique_ptr<const InstructionSetFeatures> instruction_set_features_; 121944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko MultiOatRelativePatcher patcher_; 122944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko MockPatcher* mock_; 123944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko}; 124944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 125944da603cde59a4277f3bbc31d860a90842a1a2aVladimir MarkoTEST_F(MultiOatRelativePatcherTest, Offsets) { 126944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko const DexFile* dex_file = reinterpret_cast<const DexFile*>(1); 127944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko MethodReference ref1(dex_file, 1u); 128944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko MethodReference ref2(dex_file, 2u); 129944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko EXPECT_EQ(0u, patcher_.GetOffset(ref1)); 130944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko EXPECT_EQ(0u, patcher_.GetOffset(ref2)); 131944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 132944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t adjustment1 = 0x1000; 133944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko patcher_.StartOatFile(adjustment1); 134944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko EXPECT_EQ(0u, patcher_.GetOffset(ref1)); 135944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko EXPECT_EQ(0u, patcher_.GetOffset(ref2)); 136944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 137944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t off1 = 0x1234; 138944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko patcher_.SetOffset(ref1, off1); 139944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko EXPECT_EQ(off1, patcher_.GetOffset(ref1)); 140944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko EXPECT_EQ(0u, patcher_.GetOffset(ref2)); 141944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 142944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t adjustment2 = 0x30000; 143944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko patcher_.StartOatFile(adjustment2); 144944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko EXPECT_EQ(off1 + adjustment1 - adjustment2, patcher_.GetOffset(ref1)); 145944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko EXPECT_EQ(0u, patcher_.GetOffset(ref2)); 146944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 147944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t off2 = 0x4321; 148944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko patcher_.SetOffset(ref2, off2); 149944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko EXPECT_EQ(off1 + adjustment1 - adjustment2, patcher_.GetOffset(ref1)); 150944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko EXPECT_EQ(off2, patcher_.GetOffset(ref2)); 151944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 152944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t adjustment3 = 0x78000; 153944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko patcher_.StartOatFile(adjustment3); 154944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko EXPECT_EQ(off1 + adjustment1 - adjustment3, patcher_.GetOffset(ref1)); 155944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko EXPECT_EQ(off2 + adjustment2 - adjustment3, patcher_.GetOffset(ref2)); 156944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko} 157944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 158944da603cde59a4277f3bbc31d860a90842a1a2aVladimir MarkoTEST_F(MultiOatRelativePatcherTest, OffsetsInReserve) { 159944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko const DexFile* dex_file = reinterpret_cast<const DexFile*>(1); 160944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko MethodReference ref1(dex_file, 1u); 161944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko MethodReference ref2(dex_file, 2u); 162944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko MethodReference ref3(dex_file, 3u); 163944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko const CompiledMethod* method = reinterpret_cast<const CompiledMethod*>(-1); 164944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 165944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t adjustment1 = 0x1000; 166944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko patcher_.StartOatFile(adjustment1); 167944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 168944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method1_offset = 0x100; 169944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method1_offset_check = patcher_.ReserveSpace(method1_offset, method, ref1); 170944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(adjustment1 + method1_offset, mock_->last_reserve_offset_); 171944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_TRUE(EqualRef(ref1, mock_->last_reserve_method_)); 172944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(method1_offset, method1_offset_check); 173944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 174944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method2_offset = 0x1230; 175944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method2_reserve_adjustment = 0x10; 176944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko mock_->next_reserve_adjustment_ = method2_reserve_adjustment; 177944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method2_offset_adjusted = patcher_.ReserveSpace(method2_offset, method, ref2); 178944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(adjustment1 + method2_offset, mock_->last_reserve_offset_); 179944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_TRUE(EqualRef(ref2, mock_->last_reserve_method_)); 180944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(method2_offset + method2_reserve_adjustment, method2_offset_adjusted); 181944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 182944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t end1_offset = 0x4320; 183944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t end1_offset_check = patcher_.ReserveSpaceEnd(end1_offset); 184944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(adjustment1 + end1_offset, mock_->last_reserve_offset_); 185944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_TRUE(EqualRef(kNullMethodRef, mock_->last_reserve_method_)); 186944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(end1_offset, end1_offset_check); 187944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 188944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t adjustment2 = 0xd000; 189944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko patcher_.StartOatFile(adjustment2); 190944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 191944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method3_offset = 0xf00; 192944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method3_offset_check = patcher_.ReserveSpace(method3_offset, method, ref3); 193944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(adjustment2 + method3_offset, mock_->last_reserve_offset_); 194944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_TRUE(EqualRef(ref3, mock_->last_reserve_method_)); 195944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(method3_offset, method3_offset_check); 196944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 197944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t end2_offset = 0x2400; 198944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t end2_reserve_adjustment = 0x20; 199944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko mock_->next_reserve_adjustment_ = end2_reserve_adjustment; 200944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t end2_offset_adjusted = patcher_.ReserveSpaceEnd(end2_offset); 201944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(adjustment2 + end2_offset, mock_->last_reserve_offset_); 202944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_TRUE(EqualRef(kNullMethodRef, mock_->last_reserve_method_)); 203944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(end2_offset + end2_reserve_adjustment, end2_offset_adjusted); 204944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko} 205944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 206944da603cde59a4277f3bbc31d860a90842a1a2aVladimir MarkoTEST_F(MultiOatRelativePatcherTest, Write) { 207944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko std::vector<uint8_t> output; 208944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko VectorOutputStream vos("output", &output); 209944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 210944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t adjustment1 = 0x1000; 211944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko patcher_.StartOatFile(adjustment1); 212944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 213944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method1_offset = 0x100; 214944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method1_offset_check = patcher_.WriteThunks(&vos, method1_offset); 215944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(adjustment1 + method1_offset, mock_->last_write_offset_); 216944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(method1_offset, method1_offset_check); 217944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko vos.WriteFully("1", 1); // Mark method1. 218944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 219944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method2_offset = 0x1230; 220944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method2_alignment_size = 1; 221944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method2_call_thunk_size = 2; 222944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko mock_->next_write_alignment_ = method2_alignment_size; 223944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko mock_->next_write_call_thunk_ = method2_call_thunk_size; 224944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method2_offset_adjusted = patcher_.WriteThunks(&vos, method2_offset); 225944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(adjustment1 + method2_offset, mock_->last_write_offset_); 226944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(method2_offset + method2_alignment_size + method2_call_thunk_size, 227944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko method2_offset_adjusted); 228944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko vos.WriteFully("2", 1); // Mark method2. 229944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 230944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko EXPECT_EQ(method2_alignment_size, patcher_.CodeAlignmentSize()); 231944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko EXPECT_EQ(method2_call_thunk_size, patcher_.RelativeCallThunksSize()); 232944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 233944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t adjustment2 = 0xd000; 234944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko patcher_.StartOatFile(adjustment2); 235944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 236944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method3_offset = 0xf00; 237944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method3_alignment_size = 2; 238944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method3_misc_thunk_size = 1; 239944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko mock_->next_write_alignment_ = method3_alignment_size; 240944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko mock_->next_write_misc_thunk_ = method3_misc_thunk_size; 241944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method3_offset_adjusted = patcher_.WriteThunks(&vos, method3_offset); 242944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(adjustment2 + method3_offset, mock_->last_write_offset_); 243944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(method3_offset + method3_alignment_size + method3_misc_thunk_size, 244944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko method3_offset_adjusted); 245944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko vos.WriteFully("3", 1); // Mark method3. 246944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 247944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko EXPECT_EQ(method3_alignment_size, patcher_.CodeAlignmentSize()); 248944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko EXPECT_EQ(method3_misc_thunk_size, patcher_.MiscThunksSize()); 249944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 250944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint8_t expected_output[] = { 251944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko '1', 252944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 0, 'c', 'c', '2', 253944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 0, 0, 'm', '3', 254944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko }; 255944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(arraysize(expected_output), output.size()); 256944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko for (size_t i = 0; i != arraysize(expected_output); ++i) { 257944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko ASSERT_EQ(expected_output[i], output[i]) << i; 258944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko } 259944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko} 260944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 261944da603cde59a4277f3bbc31d860a90842a1a2aVladimir MarkoTEST_F(MultiOatRelativePatcherTest, Patch) { 262944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko std::vector<uint8_t> code(16); 263944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 264944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t adjustment1 = 0x1000; 265944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko patcher_.StartOatFile(adjustment1); 266944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 267944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method1_literal_offset = 4u; 268944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method1_patch_offset = 0x1234u; 269944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method1_target_offset = 0x8888u; 270944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko patcher_.PatchCall(&code, method1_literal_offset, method1_patch_offset, method1_target_offset); 271944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko DCHECK_EQ(method1_literal_offset, mock_->last_literal_offset_); 272944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko DCHECK_EQ(method1_patch_offset + adjustment1, mock_->last_patch_offset_); 273944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko DCHECK_EQ(method1_target_offset + adjustment1, mock_->last_target_offset_); 274944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 275944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method2_literal_offset = 12u; 276944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method2_patch_offset = 0x7654u; 277944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method2_target_offset = 0xccccu; 278944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko LinkerPatch method2_patch = 279944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko LinkerPatch::DexCacheArrayPatch(method2_literal_offset, nullptr, 0u, 1234u); 280cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko patcher_.PatchPcRelativeReference( 281944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko &code, method2_patch, method2_patch_offset, method2_target_offset); 282944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko DCHECK_EQ(method2_literal_offset, mock_->last_literal_offset_); 283944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko DCHECK_EQ(method2_patch_offset + adjustment1, mock_->last_patch_offset_); 284944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko DCHECK_EQ(method2_target_offset + adjustment1, mock_->last_target_offset_); 285944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 286944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t adjustment2 = 0xd000; 287944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko patcher_.StartOatFile(adjustment2); 288944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 289944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method3_literal_offset = 8u; 290944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method3_patch_offset = 0x108u; 291944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko uint32_t method3_target_offset = 0x200u; 292944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko patcher_.PatchCall(&code, method3_literal_offset, method3_patch_offset, method3_target_offset); 293944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko DCHECK_EQ(method3_literal_offset, mock_->last_literal_offset_); 294944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko DCHECK_EQ(method3_patch_offset + adjustment2, mock_->last_patch_offset_); 295944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko DCHECK_EQ(method3_target_offset + adjustment2, mock_->last_target_offset_); 296944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko} 297944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 298944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko} // namespace linker 299944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko} // namespace art 300