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/mips/relative_patcher_mips.h" 18e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 19e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze#include "compiled_method.h" 201b404a8b34f6fa80342955cb0a61673503328b51Vladimir Marko#include "debug/method_debug_info.h" 21d8dbc8da0e5cc6b5c2176ce2d3877e6194d72c0cVladimir Marko#include "linker/linker_patch.h" 22e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 23e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunzenamespace art { 24e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunzenamespace linker { 25e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 26e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunzeuint32_t MipsRelativePatcher::ReserveSpace( 27e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze uint32_t offset, 28e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze const CompiledMethod* compiled_method ATTRIBUTE_UNUSED, 29e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze MethodReference method_ref ATTRIBUTE_UNUSED) { 30e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze return offset; // No space reserved; no limit on relative call distance. 31e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze} 32e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 33e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunzeuint32_t MipsRelativePatcher::ReserveSpaceEnd(uint32_t offset) { 34e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze return offset; // No space reserved; no limit on relative call distance. 35e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze} 36e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 37e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunzeuint32_t MipsRelativePatcher::WriteThunks(OutputStream* out ATTRIBUTE_UNUSED, uint32_t offset) { 38e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze return offset; // No thunks added; no limit on relative call distance. 39e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze} 40e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 41e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunzevoid MipsRelativePatcher::PatchCall(std::vector<uint8_t>* code ATTRIBUTE_UNUSED, 42e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze uint32_t literal_offset ATTRIBUTE_UNUSED, 43e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze uint32_t patch_offset ATTRIBUTE_UNUSED, 44e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze uint32_t target_offset ATTRIBUTE_UNUSED) { 45e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze UNIMPLEMENTED(FATAL) << "PatchCall unimplemented on MIPS"; 46e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze} 47e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 48e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunzevoid MipsRelativePatcher::PatchPcRelativeReference(std::vector<uint8_t>* code, 49e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze const LinkerPatch& patch, 50e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze uint32_t patch_offset, 51e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze uint32_t target_offset) { 52e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze uint32_t anchor_literal_offset = patch.PcInsnOffset(); 53e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze uint32_t literal_offset = patch.LiteralOffset(); 545fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze bool high_patch = ((*code)[literal_offset + 0] == 0x34) && ((*code)[literal_offset + 1] == 0x12); 55e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 565fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze // Perform basic sanity checks. 575fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze if (high_patch) { 585fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze if (is_r6) { 595fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze // auipc reg, offset_high 605fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze DCHECK_EQ(((*code)[literal_offset + 2] & 0x1F), 0x1E); 615fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze DCHECK_EQ(((*code)[literal_offset + 3] & 0xFC), 0xEC); 625fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze } else { 635fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze // lui reg, offset_high 645fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze DCHECK_EQ(((*code)[literal_offset + 2] & 0xE0), 0x00); 655fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze DCHECK_EQ((*code)[literal_offset + 3], 0x3C); 665fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze } 67e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze } else { 686b892cd757db7e163b54c8a0ef5ba777b1a4772cAlexey Frunze // instr reg(s), offset_low 695fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze CHECK_EQ((*code)[literal_offset + 0], 0x78); 705fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze CHECK_EQ((*code)[literal_offset + 1], 0x56); 71e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze } 72e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 73e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze // Apply patch. 74e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze uint32_t anchor_offset = patch_offset - literal_offset + anchor_literal_offset; 7506a46c44bf1a5cba6c78c3faffc4e7ec1442b210Alexey Frunze uint32_t diff = target_offset - anchor_offset; 766b892cd757db7e163b54c8a0ef5ba777b1a4772cAlexey Frunze diff += (diff & 0x8000) << 1; // Account for sign extension in "instr reg(s), offset_low". 77e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 785fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze if (high_patch) { 795fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze // lui reg, offset_high / auipc reg, offset_high 805fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze (*code)[literal_offset + 0] = static_cast<uint8_t>(diff >> 16); 815fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze (*code)[literal_offset + 1] = static_cast<uint8_t>(diff >> 24); 825fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze } else { 835fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze // instr reg(s), offset_low 845fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze (*code)[literal_offset + 0] = static_cast<uint8_t>(diff >> 0); 855fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze (*code)[literal_offset + 1] = static_cast<uint8_t>(diff >> 8); 865fa5c04ca39fb9c46bfef0e0807a18d0cd9a4ba7Alexey Frunze } 87e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze} 88e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze 89f4f2daafb38c9c07ea74044a0fb89a2a19288b7aVladimir Markovoid MipsRelativePatcher::PatchBakerReadBarrierBranch(std::vector<uint8_t>* code ATTRIBUTE_UNUSED, 90f4f2daafb38c9c07ea74044a0fb89a2a19288b7aVladimir Marko const LinkerPatch& patch ATTRIBUTE_UNUSED, 91f4f2daafb38c9c07ea74044a0fb89a2a19288b7aVladimir Marko uint32_t patch_offset ATTRIBUTE_UNUSED) { 92f4f2daafb38c9c07ea74044a0fb89a2a19288b7aVladimir Marko LOG(FATAL) << "UNIMPLEMENTED"; 93f4f2daafb38c9c07ea74044a0fb89a2a19288b7aVladimir Marko} 94f4f2daafb38c9c07ea74044a0fb89a2a19288b7aVladimir Marko 951b404a8b34f6fa80342955cb0a61673503328b51Vladimir Markostd::vector<debug::MethodDebugInfo> MipsRelativePatcher::GenerateThunkDebugInfo( 961b404a8b34f6fa80342955cb0a61673503328b51Vladimir Marko uint32_t executable_offset ATTRIBUTE_UNUSED) { 971b404a8b34f6fa80342955cb0a61673503328b51Vladimir Marko return std::vector<debug::MethodDebugInfo>(); // No thunks added. 981b404a8b34f6fa80342955cb0a61673503328b51Vladimir Marko} 991b404a8b34f6fa80342955cb0a61673503328b51Vladimir Marko 100e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze} // namespace linker 101e3fb245fbdb5e91cf8a9750504df40bd629e0080Alexey Frunze} // namespace art 102