xref: /aosp_15_r20/art/dex2oat/linker/x86/relative_patcher_x86.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "linker/x86/relative_patcher_x86.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include "linker/linker_patch.h"
20*795d594fSAndroid Build Coastguard Worker 
21*795d594fSAndroid Build Coastguard Worker namespace art {
22*795d594fSAndroid Build Coastguard Worker namespace linker {
23*795d594fSAndroid Build Coastguard Worker 
PatchPcRelativeReference(std::vector<uint8_t> * code,const LinkerPatch & patch,uint32_t patch_offset,uint32_t target_offset)24*795d594fSAndroid Build Coastguard Worker void X86RelativePatcher::PatchPcRelativeReference(std::vector<uint8_t>* code,
25*795d594fSAndroid Build Coastguard Worker                                                   const LinkerPatch& patch,
26*795d594fSAndroid Build Coastguard Worker                                                   uint32_t patch_offset,
27*795d594fSAndroid Build Coastguard Worker                                                   uint32_t target_offset) {
28*795d594fSAndroid Build Coastguard Worker   uint32_t anchor_literal_offset = patch.PcInsnOffset();
29*795d594fSAndroid Build Coastguard Worker   uint32_t literal_offset = patch.LiteralOffset();
30*795d594fSAndroid Build Coastguard Worker 
31*795d594fSAndroid Build Coastguard Worker   // Check that the anchor points to pop in a "call +0; pop <reg>" sequence.
32*795d594fSAndroid Build Coastguard Worker   DCHECK_GE(anchor_literal_offset, 5u);
33*795d594fSAndroid Build Coastguard Worker   DCHECK_LT(anchor_literal_offset, code->size());
34*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ((*code)[anchor_literal_offset - 5u], 0xe8u);
35*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ((*code)[anchor_literal_offset - 4u], 0x00u);
36*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ((*code)[anchor_literal_offset - 3u], 0x00u);
37*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ((*code)[anchor_literal_offset - 2u], 0x00u);
38*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ((*code)[anchor_literal_offset - 1u], 0x00u);
39*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ((*code)[anchor_literal_offset] & 0xf8u, 0x58u);
40*795d594fSAndroid Build Coastguard Worker 
41*795d594fSAndroid Build Coastguard Worker   // Check that the patched data contains kPlaceholder32BitOffset.
42*795d594fSAndroid Build Coastguard Worker   // Must match CodeGeneratorX86_64::kPlaceholder32BitOffset.
43*795d594fSAndroid Build Coastguard Worker   constexpr int kPlaceholder32BitOffset = 256;
44*795d594fSAndroid Build Coastguard Worker   DCHECK_LE(literal_offset, code->size());
45*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ((*code)[literal_offset + 0u], static_cast<uint8_t>(kPlaceholder32BitOffset >> 0));
46*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ((*code)[literal_offset + 1u], static_cast<uint8_t>(kPlaceholder32BitOffset >> 8));
47*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ((*code)[literal_offset + 2u], static_cast<uint8_t>(kPlaceholder32BitOffset >> 16));
48*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ((*code)[literal_offset + 3u], static_cast<uint8_t>(kPlaceholder32BitOffset >> 24));
49*795d594fSAndroid Build Coastguard Worker 
50*795d594fSAndroid Build Coastguard Worker   // Apply patch.
51*795d594fSAndroid Build Coastguard Worker   uint32_t anchor_offset = patch_offset - literal_offset + anchor_literal_offset;
52*795d594fSAndroid Build Coastguard Worker   uint32_t diff = target_offset - anchor_offset;
53*795d594fSAndroid Build Coastguard Worker   (*code)[literal_offset + 0u] = static_cast<uint8_t>(diff >> 0);
54*795d594fSAndroid Build Coastguard Worker   (*code)[literal_offset + 1u] = static_cast<uint8_t>(diff >> 8);
55*795d594fSAndroid Build Coastguard Worker   (*code)[literal_offset + 2u] = static_cast<uint8_t>(diff >> 16);
56*795d594fSAndroid Build Coastguard Worker   (*code)[literal_offset + 3u] = static_cast<uint8_t>(diff >> 24);
57*795d594fSAndroid Build Coastguard Worker }
58*795d594fSAndroid Build Coastguard Worker 
PatchEntrypointCall(std::vector<uint8_t> * code,const LinkerPatch & patch,uint32_t patch_offset)59*795d594fSAndroid Build Coastguard Worker void X86RelativePatcher::PatchEntrypointCall([[maybe_unused]] std::vector<uint8_t>* code,
60*795d594fSAndroid Build Coastguard Worker                                              [[maybe_unused]] const LinkerPatch& patch,
61*795d594fSAndroid Build Coastguard Worker                                              [[maybe_unused]] uint32_t patch_offset) {
62*795d594fSAndroid Build Coastguard Worker   LOG(FATAL) << "UNIMPLEMENTED";
63*795d594fSAndroid Build Coastguard Worker }
64*795d594fSAndroid Build Coastguard Worker 
PatchBakerReadBarrierBranch(std::vector<uint8_t> * code,const LinkerPatch & patch,uint32_t patch_offset)65*795d594fSAndroid Build Coastguard Worker void X86RelativePatcher::PatchBakerReadBarrierBranch([[maybe_unused]] std::vector<uint8_t>* code,
66*795d594fSAndroid Build Coastguard Worker                                                      [[maybe_unused]] const LinkerPatch& patch,
67*795d594fSAndroid Build Coastguard Worker                                                      [[maybe_unused]] uint32_t patch_offset) {
68*795d594fSAndroid Build Coastguard Worker   LOG(FATAL) << "UNIMPLEMENTED";
69*795d594fSAndroid Build Coastguard Worker }
70*795d594fSAndroid Build Coastguard Worker 
71*795d594fSAndroid Build Coastguard Worker }  // namespace linker
72*795d594fSAndroid Build Coastguard Worker }  // namespace art
73