1e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze/* 2e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze * Copyright (C) 2016 The Android Open Source Project 3e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze * 4e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze * Licensed under the Apache License, Version 2.0 (the "License"); 5e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze * you may not use this file except in compliance with the License. 6e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze * You may obtain a copy of the License at 7e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze * 8e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze * http://www.apache.org/licenses/LICENSE-2.0 9e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze * 10e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze * Unless required by applicable law or agreed to in writing, software 11e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze * distributed under the License is distributed on an "AS IS" BASIS, 12e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze * See the License for the specific language governing permissions and 14e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze * limitations under the License. 15e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze */ 16e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 17e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze#include "linker/relative_patcher_test.h" 18e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze#include "linker/mips/relative_patcher_mips.h" 19e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 20e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunzenamespace art { 21e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunzenamespace linker { 22e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 23e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunzeclass Mips32r6RelativePatcherTest : public RelativePatcherTest { 24e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze public: 25e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze Mips32r6RelativePatcherTest() : RelativePatcherTest(kMips, "mips32r6") {} 26e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 27e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze protected: 2819f6c696bbb7a17d8ac521b316c40f9cbef32151Alexey Frunze static const uint8_t kUnpatchedPcRelativeRawCode[]; 2919f6c696bbb7a17d8ac521b316c40f9cbef32151Alexey Frunze static const uint32_t kLiteralOffset; 3019f6c696bbb7a17d8ac521b316c40f9cbef32151Alexey Frunze static const uint32_t kAnchorOffset; 3119f6c696bbb7a17d8ac521b316c40f9cbef32151Alexey Frunze static const ArrayRef<const uint8_t> kUnpatchedPcRelativeCode; 3206a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze 33e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze uint32_t GetMethodOffset(uint32_t method_idx) { 34e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze auto result = method_offset_map_.FindMethodOffset(MethodRef(method_idx)); 35e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze CHECK(result.first); 36e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze return result.second; 37e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze } 3806a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze 3906a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze void CheckPcRelativePatch(const ArrayRef<const LinkerPatch>& patches, uint32_t target_offset); 4006a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze void TestDexCacheReference(uint32_t dex_cache_arrays_begin, uint32_t element_offset); 4106a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze void TestStringReference(uint32_t string_offset); 42e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze}; 43e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 4419f6c696bbb7a17d8ac521b316c40f9cbef32151Alexey Frunzeconst uint8_t Mips32r6RelativePatcherTest::kUnpatchedPcRelativeRawCode[] = { 4506a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze 0x34, 0x12, 0x5E, 0xEE, // auipc s2, high(diff); placeholder = 0x1234 4606a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze 0x78, 0x56, 0x52, 0x26, // addiu s2, s2, low(diff); placeholder = 0x5678 4706a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze}; 4819f6c696bbb7a17d8ac521b316c40f9cbef32151Alexey Frunzeconst uint32_t Mips32r6RelativePatcherTest::kLiteralOffset = 0; // At auipc (where 4919f6c696bbb7a17d8ac521b316c40f9cbef32151Alexey Frunze // patching starts). 5019f6c696bbb7a17d8ac521b316c40f9cbef32151Alexey Frunzeconst uint32_t Mips32r6RelativePatcherTest::kAnchorOffset = 0; // At auipc (where PC+0 points). 5119f6c696bbb7a17d8ac521b316c40f9cbef32151Alexey Frunzeconst ArrayRef<const uint8_t> Mips32r6RelativePatcherTest::kUnpatchedPcRelativeCode( 5219f6c696bbb7a17d8ac521b316c40f9cbef32151Alexey Frunze kUnpatchedPcRelativeRawCode); 5306a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze 5406a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunzevoid Mips32r6RelativePatcherTest::CheckPcRelativePatch(const ArrayRef<const LinkerPatch>& patches, 5506a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze uint32_t target_offset) { 5619f6c696bbb7a17d8ac521b316c40f9cbef32151Alexey Frunze AddCompiledMethod(MethodRef(1u), kUnpatchedPcRelativeCode, ArrayRef<const LinkerPatch>(patches)); 57e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze Link(); 58e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 59e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze auto result = method_offset_map_.FindMethodOffset(MethodRef(1u)); 60e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze ASSERT_TRUE(result.first); 6106a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze 6219f6c696bbb7a17d8ac521b316c40f9cbef32151Alexey Frunze uint32_t diff = target_offset - (result.second + kAnchorOffset); 63e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze diff += (diff & 0x8000) << 1; // Account for sign extension in addiu. 6406a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze 6506a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze const uint8_t expected_code[] = { 66e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze static_cast<uint8_t>(diff >> 16), static_cast<uint8_t>(diff >> 24), 0x5E, 0xEE, 67e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze static_cast<uint8_t>(diff), static_cast<uint8_t>(diff >> 8), 0x52, 0x26, 68e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze }; 69e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze EXPECT_TRUE(CheckLinkedMethod(MethodRef(1u), ArrayRef<const uint8_t>(expected_code))); 70e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze} 71e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 7206a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunzevoid Mips32r6RelativePatcherTest::TestDexCacheReference(uint32_t dex_cache_arrays_begin, 7306a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze uint32_t element_offset) { 7406a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze dex_cache_arrays_begin_ = dex_cache_arrays_begin; 7506a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze LinkerPatch patches[] = { 7619f6c696bbb7a17d8ac521b316c40f9cbef32151Alexey Frunze LinkerPatch::DexCacheArrayPatch(kLiteralOffset, nullptr, kAnchorOffset, element_offset) 7706a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze }; 7806a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze CheckPcRelativePatch(ArrayRef<const LinkerPatch>(patches), 7906a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze dex_cache_arrays_begin_ + element_offset); 8006a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze} 8106a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze 8206a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunzevoid Mips32r6RelativePatcherTest::TestStringReference(uint32_t string_offset) { 8306a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze constexpr uint32_t kStringIndex = 1u; 8406a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze string_index_to_offset_map_.Put(kStringIndex, string_offset); 8506a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze LinkerPatch patches[] = { 8619f6c696bbb7a17d8ac521b316c40f9cbef32151Alexey Frunze LinkerPatch::RelativeStringPatch(kLiteralOffset, nullptr, kAnchorOffset, kStringIndex) 8706a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze }; 8806a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze CheckPcRelativePatch(ArrayRef<const LinkerPatch>(patches), string_offset); 8906a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze} 9006a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze 9106a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey FrunzeTEST_F(Mips32r6RelativePatcherTest, DexCacheReference) { 9206a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze TestDexCacheReference(/* dex_cache_arrays_begin */ 0x12345678, /* element_offset */ 0x1234); 9306a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze} 9406a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze 9506a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey FrunzeTEST_F(Mips32r6RelativePatcherTest, StringReference) { 9606a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze TestStringReference(/* string_offset*/ 0x87651234); 9706a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze} 9806a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze 99e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze} // namespace linker 100e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze} // namespace art 101