xref: /aosp_15_r20/art/compiler/linker/linker_patch.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2017 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 #ifndef ART_COMPILER_LINKER_LINKER_PATCH_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_LINKER_LINKER_PATCH_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <iosfwd>
21*795d594fSAndroid Build Coastguard Worker #include <stdint.h>
22*795d594fSAndroid Build Coastguard Worker 
23*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
24*795d594fSAndroid Build Coastguard Worker 
25*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h"
26*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
27*795d594fSAndroid Build Coastguard Worker #include "dex/method_reference.h"
28*795d594fSAndroid Build Coastguard Worker #include "dex/proto_reference.h"
29*795d594fSAndroid Build Coastguard Worker #include "dex/string_reference.h"
30*795d594fSAndroid Build Coastguard Worker #include "dex/type_reference.h"
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker class DexFile;
35*795d594fSAndroid Build Coastguard Worker 
36*795d594fSAndroid Build Coastguard Worker namespace linker {
37*795d594fSAndroid Build Coastguard Worker 
38*795d594fSAndroid Build Coastguard Worker class LinkerPatch {
39*795d594fSAndroid Build Coastguard Worker  public:
40*795d594fSAndroid Build Coastguard Worker   // Note: We explicitly specify the underlying type of the enum because GCC
41*795d594fSAndroid Build Coastguard Worker   // would otherwise select a bigger underlying type and then complain that
42*795d594fSAndroid Build Coastguard Worker   //     'art::LinkerPatch::patch_type_' is too small to hold all
43*795d594fSAndroid Build Coastguard Worker   //     values of 'enum class art::LinkerPatch::Type'
44*795d594fSAndroid Build Coastguard Worker   // which is ridiculous given we have only a handful of values here. If we
45*795d594fSAndroid Build Coastguard Worker   // choose to squeeze the Type into fewer than 8 bits, we'll have to declare
46*795d594fSAndroid Build Coastguard Worker   // patch_type_ as an uintN_t and do explicit static_cast<>s.
47*795d594fSAndroid Build Coastguard Worker   //
48*795d594fSAndroid Build Coastguard Worker   // Note: Actual patching is instruction_set-dependent.
49*795d594fSAndroid Build Coastguard Worker   enum class Type : uint8_t {
50*795d594fSAndroid Build Coastguard Worker     kIntrinsicReference,      // Boot image reference for an intrinsic, see IntrinsicObjects.
51*795d594fSAndroid Build Coastguard Worker     kBootImageRelRo,
52*795d594fSAndroid Build Coastguard Worker     kMethodRelative,
53*795d594fSAndroid Build Coastguard Worker     kMethodAppImageRelRo,
54*795d594fSAndroid Build Coastguard Worker     kMethodBssEntry,
55*795d594fSAndroid Build Coastguard Worker     kJniEntrypointRelative,
56*795d594fSAndroid Build Coastguard Worker     kCallRelative,
57*795d594fSAndroid Build Coastguard Worker     kTypeRelative,
58*795d594fSAndroid Build Coastguard Worker     kTypeAppImageRelRo,
59*795d594fSAndroid Build Coastguard Worker     kTypeBssEntry,
60*795d594fSAndroid Build Coastguard Worker     kPublicTypeBssEntry,
61*795d594fSAndroid Build Coastguard Worker     kPackageTypeBssEntry,
62*795d594fSAndroid Build Coastguard Worker     kStringRelative,
63*795d594fSAndroid Build Coastguard Worker     kStringBssEntry,
64*795d594fSAndroid Build Coastguard Worker     kMethodTypeBssEntry,
65*795d594fSAndroid Build Coastguard Worker     kCallEntrypoint,
66*795d594fSAndroid Build Coastguard Worker     kBakerReadBarrierBranch,
67*795d594fSAndroid Build Coastguard Worker   };
68*795d594fSAndroid Build Coastguard Worker 
IntrinsicReferencePatch(size_t literal_offset,uint32_t pc_insn_offset,uint32_t intrinsic_data)69*795d594fSAndroid Build Coastguard Worker   static LinkerPatch IntrinsicReferencePatch(size_t literal_offset,
70*795d594fSAndroid Build Coastguard Worker                                              uint32_t pc_insn_offset,
71*795d594fSAndroid Build Coastguard Worker                                              uint32_t intrinsic_data) {
72*795d594fSAndroid Build Coastguard Worker     LinkerPatch patch(literal_offset, Type::kIntrinsicReference, /* target_dex_file= */ nullptr);
73*795d594fSAndroid Build Coastguard Worker     patch.intrinsic_data_ = intrinsic_data;
74*795d594fSAndroid Build Coastguard Worker     patch.pc_insn_offset_ = pc_insn_offset;
75*795d594fSAndroid Build Coastguard Worker     return patch;
76*795d594fSAndroid Build Coastguard Worker   }
77*795d594fSAndroid Build Coastguard Worker 
BootImageRelRoPatch(size_t literal_offset,uint32_t pc_insn_offset,uint32_t boot_image_offset)78*795d594fSAndroid Build Coastguard Worker   static LinkerPatch BootImageRelRoPatch(size_t literal_offset,
79*795d594fSAndroid Build Coastguard Worker                                          uint32_t pc_insn_offset,
80*795d594fSAndroid Build Coastguard Worker                                          uint32_t boot_image_offset) {
81*795d594fSAndroid Build Coastguard Worker     LinkerPatch patch(literal_offset, Type::kBootImageRelRo, /* target_dex_file= */ nullptr);
82*795d594fSAndroid Build Coastguard Worker     patch.boot_image_offset_ = boot_image_offset;
83*795d594fSAndroid Build Coastguard Worker     patch.pc_insn_offset_ = pc_insn_offset;
84*795d594fSAndroid Build Coastguard Worker     return patch;
85*795d594fSAndroid Build Coastguard Worker   }
86*795d594fSAndroid Build Coastguard Worker 
RelativeMethodPatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t target_method_idx)87*795d594fSAndroid Build Coastguard Worker   static LinkerPatch RelativeMethodPatch(size_t literal_offset,
88*795d594fSAndroid Build Coastguard Worker                                          const DexFile* target_dex_file,
89*795d594fSAndroid Build Coastguard Worker                                          uint32_t pc_insn_offset,
90*795d594fSAndroid Build Coastguard Worker                                          uint32_t target_method_idx) {
91*795d594fSAndroid Build Coastguard Worker     LinkerPatch patch(literal_offset, Type::kMethodRelative, target_dex_file);
92*795d594fSAndroid Build Coastguard Worker     patch.method_idx_ = target_method_idx;
93*795d594fSAndroid Build Coastguard Worker     patch.pc_insn_offset_ = pc_insn_offset;
94*795d594fSAndroid Build Coastguard Worker     return patch;
95*795d594fSAndroid Build Coastguard Worker   }
96*795d594fSAndroid Build Coastguard Worker 
MethodAppImageRelRoPatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t target_method_idx)97*795d594fSAndroid Build Coastguard Worker   static LinkerPatch MethodAppImageRelRoPatch(size_t literal_offset,
98*795d594fSAndroid Build Coastguard Worker                                               const DexFile* target_dex_file,
99*795d594fSAndroid Build Coastguard Worker                                               uint32_t pc_insn_offset,
100*795d594fSAndroid Build Coastguard Worker                                               uint32_t target_method_idx) {
101*795d594fSAndroid Build Coastguard Worker     LinkerPatch patch(literal_offset, Type::kMethodAppImageRelRo, target_dex_file);
102*795d594fSAndroid Build Coastguard Worker     patch.method_idx_ = target_method_idx;
103*795d594fSAndroid Build Coastguard Worker     patch.pc_insn_offset_ = pc_insn_offset;
104*795d594fSAndroid Build Coastguard Worker     return patch;
105*795d594fSAndroid Build Coastguard Worker   }
106*795d594fSAndroid Build Coastguard Worker 
MethodBssEntryPatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t target_method_idx)107*795d594fSAndroid Build Coastguard Worker   static LinkerPatch MethodBssEntryPatch(size_t literal_offset,
108*795d594fSAndroid Build Coastguard Worker                                          const DexFile* target_dex_file,
109*795d594fSAndroid Build Coastguard Worker                                          uint32_t pc_insn_offset,
110*795d594fSAndroid Build Coastguard Worker                                          uint32_t target_method_idx) {
111*795d594fSAndroid Build Coastguard Worker     LinkerPatch patch(literal_offset, Type::kMethodBssEntry, target_dex_file);
112*795d594fSAndroid Build Coastguard Worker     patch.method_idx_ = target_method_idx;
113*795d594fSAndroid Build Coastguard Worker     patch.pc_insn_offset_ = pc_insn_offset;
114*795d594fSAndroid Build Coastguard Worker     return patch;
115*795d594fSAndroid Build Coastguard Worker   }
116*795d594fSAndroid Build Coastguard Worker 
RelativeJniEntrypointPatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t target_method_idx)117*795d594fSAndroid Build Coastguard Worker   static LinkerPatch RelativeJniEntrypointPatch(size_t literal_offset,
118*795d594fSAndroid Build Coastguard Worker                                                 const DexFile* target_dex_file,
119*795d594fSAndroid Build Coastguard Worker                                                 uint32_t pc_insn_offset,
120*795d594fSAndroid Build Coastguard Worker                                                 uint32_t target_method_idx) {
121*795d594fSAndroid Build Coastguard Worker     LinkerPatch patch(literal_offset, Type::kJniEntrypointRelative, target_dex_file);
122*795d594fSAndroid Build Coastguard Worker     patch.method_idx_ = target_method_idx;
123*795d594fSAndroid Build Coastguard Worker     patch.pc_insn_offset_ = pc_insn_offset;
124*795d594fSAndroid Build Coastguard Worker     return patch;
125*795d594fSAndroid Build Coastguard Worker   }
126*795d594fSAndroid Build Coastguard Worker 
RelativeCodePatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t target_method_idx)127*795d594fSAndroid Build Coastguard Worker   static LinkerPatch RelativeCodePatch(size_t literal_offset,
128*795d594fSAndroid Build Coastguard Worker                                        const DexFile* target_dex_file,
129*795d594fSAndroid Build Coastguard Worker                                        uint32_t target_method_idx) {
130*795d594fSAndroid Build Coastguard Worker     LinkerPatch patch(literal_offset, Type::kCallRelative, target_dex_file);
131*795d594fSAndroid Build Coastguard Worker     patch.method_idx_ = target_method_idx;
132*795d594fSAndroid Build Coastguard Worker     return patch;
133*795d594fSAndroid Build Coastguard Worker   }
134*795d594fSAndroid Build Coastguard Worker 
RelativeTypePatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t target_type_idx)135*795d594fSAndroid Build Coastguard Worker   static LinkerPatch RelativeTypePatch(size_t literal_offset,
136*795d594fSAndroid Build Coastguard Worker                                        const DexFile* target_dex_file,
137*795d594fSAndroid Build Coastguard Worker                                        uint32_t pc_insn_offset,
138*795d594fSAndroid Build Coastguard Worker                                        uint32_t target_type_idx) {
139*795d594fSAndroid Build Coastguard Worker     LinkerPatch patch(literal_offset, Type::kTypeRelative, target_dex_file);
140*795d594fSAndroid Build Coastguard Worker     patch.type_idx_ = target_type_idx;
141*795d594fSAndroid Build Coastguard Worker     patch.pc_insn_offset_ = pc_insn_offset;
142*795d594fSAndroid Build Coastguard Worker     return patch;
143*795d594fSAndroid Build Coastguard Worker   }
144*795d594fSAndroid Build Coastguard Worker 
TypeAppImageRelRoPatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t target_type_idx)145*795d594fSAndroid Build Coastguard Worker   static LinkerPatch TypeAppImageRelRoPatch(size_t literal_offset,
146*795d594fSAndroid Build Coastguard Worker                                             const DexFile* target_dex_file,
147*795d594fSAndroid Build Coastguard Worker                                             uint32_t pc_insn_offset,
148*795d594fSAndroid Build Coastguard Worker                                             uint32_t target_type_idx) {
149*795d594fSAndroid Build Coastguard Worker     LinkerPatch patch(literal_offset, Type::kTypeAppImageRelRo, target_dex_file);
150*795d594fSAndroid Build Coastguard Worker     patch.type_idx_ = target_type_idx;
151*795d594fSAndroid Build Coastguard Worker     patch.pc_insn_offset_ = pc_insn_offset;
152*795d594fSAndroid Build Coastguard Worker     return patch;
153*795d594fSAndroid Build Coastguard Worker   }
154*795d594fSAndroid Build Coastguard Worker 
TypeBssEntryPatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t target_type_idx)155*795d594fSAndroid Build Coastguard Worker   static LinkerPatch TypeBssEntryPatch(size_t literal_offset,
156*795d594fSAndroid Build Coastguard Worker                                        const DexFile* target_dex_file,
157*795d594fSAndroid Build Coastguard Worker                                        uint32_t pc_insn_offset,
158*795d594fSAndroid Build Coastguard Worker                                        uint32_t target_type_idx) {
159*795d594fSAndroid Build Coastguard Worker     LinkerPatch patch(literal_offset, Type::kTypeBssEntry, target_dex_file);
160*795d594fSAndroid Build Coastguard Worker     patch.type_idx_ = target_type_idx;
161*795d594fSAndroid Build Coastguard Worker     patch.pc_insn_offset_ = pc_insn_offset;
162*795d594fSAndroid Build Coastguard Worker     return patch;
163*795d594fSAndroid Build Coastguard Worker   }
164*795d594fSAndroid Build Coastguard Worker 
PublicTypeBssEntryPatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t target_type_idx)165*795d594fSAndroid Build Coastguard Worker   static LinkerPatch PublicTypeBssEntryPatch(size_t literal_offset,
166*795d594fSAndroid Build Coastguard Worker                                              const DexFile* target_dex_file,
167*795d594fSAndroid Build Coastguard Worker                                              uint32_t pc_insn_offset,
168*795d594fSAndroid Build Coastguard Worker                                              uint32_t target_type_idx) {
169*795d594fSAndroid Build Coastguard Worker     LinkerPatch patch(literal_offset, Type::kPublicTypeBssEntry, target_dex_file);
170*795d594fSAndroid Build Coastguard Worker     patch.type_idx_ = target_type_idx;
171*795d594fSAndroid Build Coastguard Worker     patch.pc_insn_offset_ = pc_insn_offset;
172*795d594fSAndroid Build Coastguard Worker     return patch;
173*795d594fSAndroid Build Coastguard Worker   }
174*795d594fSAndroid Build Coastguard Worker 
PackageTypeBssEntryPatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t target_type_idx)175*795d594fSAndroid Build Coastguard Worker   static LinkerPatch PackageTypeBssEntryPatch(size_t literal_offset,
176*795d594fSAndroid Build Coastguard Worker                                               const DexFile* target_dex_file,
177*795d594fSAndroid Build Coastguard Worker                                               uint32_t pc_insn_offset,
178*795d594fSAndroid Build Coastguard Worker                                               uint32_t target_type_idx) {
179*795d594fSAndroid Build Coastguard Worker     LinkerPatch patch(literal_offset, Type::kPackageTypeBssEntry, target_dex_file);
180*795d594fSAndroid Build Coastguard Worker     patch.type_idx_ = target_type_idx;
181*795d594fSAndroid Build Coastguard Worker     patch.pc_insn_offset_ = pc_insn_offset;
182*795d594fSAndroid Build Coastguard Worker     return patch;
183*795d594fSAndroid Build Coastguard Worker   }
184*795d594fSAndroid Build Coastguard Worker 
RelativeStringPatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t target_string_idx)185*795d594fSAndroid Build Coastguard Worker   static LinkerPatch RelativeStringPatch(size_t literal_offset,
186*795d594fSAndroid Build Coastguard Worker                                          const DexFile* target_dex_file,
187*795d594fSAndroid Build Coastguard Worker                                          uint32_t pc_insn_offset,
188*795d594fSAndroid Build Coastguard Worker                                          uint32_t target_string_idx) {
189*795d594fSAndroid Build Coastguard Worker     LinkerPatch patch(literal_offset, Type::kStringRelative, target_dex_file);
190*795d594fSAndroid Build Coastguard Worker     patch.string_idx_ = target_string_idx;
191*795d594fSAndroid Build Coastguard Worker     patch.pc_insn_offset_ = pc_insn_offset;
192*795d594fSAndroid Build Coastguard Worker     return patch;
193*795d594fSAndroid Build Coastguard Worker   }
194*795d594fSAndroid Build Coastguard Worker 
StringBssEntryPatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t target_string_idx)195*795d594fSAndroid Build Coastguard Worker   static LinkerPatch StringBssEntryPatch(size_t literal_offset,
196*795d594fSAndroid Build Coastguard Worker                                          const DexFile* target_dex_file,
197*795d594fSAndroid Build Coastguard Worker                                          uint32_t pc_insn_offset,
198*795d594fSAndroid Build Coastguard Worker                                          uint32_t target_string_idx) {
199*795d594fSAndroid Build Coastguard Worker     LinkerPatch patch(literal_offset, Type::kStringBssEntry, target_dex_file);
200*795d594fSAndroid Build Coastguard Worker     patch.string_idx_ = target_string_idx;
201*795d594fSAndroid Build Coastguard Worker     patch.pc_insn_offset_ = pc_insn_offset;
202*795d594fSAndroid Build Coastguard Worker     return patch;
203*795d594fSAndroid Build Coastguard Worker   }
204*795d594fSAndroid Build Coastguard Worker 
MethodTypeBssEntryPatch(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t target_proto_idx)205*795d594fSAndroid Build Coastguard Worker   static LinkerPatch MethodTypeBssEntryPatch(size_t literal_offset,
206*795d594fSAndroid Build Coastguard Worker                                              const DexFile* target_dex_file,
207*795d594fSAndroid Build Coastguard Worker                                              uint32_t pc_insn_offset,
208*795d594fSAndroid Build Coastguard Worker                                              uint32_t target_proto_idx) {
209*795d594fSAndroid Build Coastguard Worker     LinkerPatch patch(literal_offset, Type::kMethodTypeBssEntry, target_dex_file);
210*795d594fSAndroid Build Coastguard Worker     patch.proto_idx_ = target_proto_idx;
211*795d594fSAndroid Build Coastguard Worker     patch.pc_insn_offset_ = pc_insn_offset;
212*795d594fSAndroid Build Coastguard Worker     return patch;
213*795d594fSAndroid Build Coastguard Worker   }
214*795d594fSAndroid Build Coastguard Worker 
CallEntrypointPatch(size_t literal_offset,uint32_t entrypoint_offset)215*795d594fSAndroid Build Coastguard Worker   static LinkerPatch CallEntrypointPatch(size_t literal_offset,
216*795d594fSAndroid Build Coastguard Worker                                          uint32_t entrypoint_offset) {
217*795d594fSAndroid Build Coastguard Worker     LinkerPatch patch(literal_offset,
218*795d594fSAndroid Build Coastguard Worker                       Type::kCallEntrypoint,
219*795d594fSAndroid Build Coastguard Worker                       /* target_dex_file= */ nullptr);
220*795d594fSAndroid Build Coastguard Worker     patch.entrypoint_offset_ = entrypoint_offset;
221*795d594fSAndroid Build Coastguard Worker     return patch;
222*795d594fSAndroid Build Coastguard Worker   }
223*795d594fSAndroid Build Coastguard Worker 
224*795d594fSAndroid Build Coastguard Worker   static LinkerPatch BakerReadBarrierBranchPatch(size_t literal_offset,
225*795d594fSAndroid Build Coastguard Worker                                                  uint32_t custom_value1 = 0u,
226*795d594fSAndroid Build Coastguard Worker                                                  uint32_t custom_value2 = 0u) {
227*795d594fSAndroid Build Coastguard Worker     LinkerPatch patch(literal_offset,
228*795d594fSAndroid Build Coastguard Worker                       Type::kBakerReadBarrierBranch,
229*795d594fSAndroid Build Coastguard Worker                       /* target_dex_file= */ nullptr);
230*795d594fSAndroid Build Coastguard Worker     patch.baker_custom_value1_ = custom_value1;
231*795d594fSAndroid Build Coastguard Worker     patch.baker_custom_value2_ = custom_value2;
232*795d594fSAndroid Build Coastguard Worker     return patch;
233*795d594fSAndroid Build Coastguard Worker   }
234*795d594fSAndroid Build Coastguard Worker 
235*795d594fSAndroid Build Coastguard Worker   LinkerPatch(const LinkerPatch& other) = default;
236*795d594fSAndroid Build Coastguard Worker   LinkerPatch& operator=(const LinkerPatch& other) = default;
237*795d594fSAndroid Build Coastguard Worker 
LiteralOffset()238*795d594fSAndroid Build Coastguard Worker   size_t LiteralOffset() const {
239*795d594fSAndroid Build Coastguard Worker     return literal_offset_;
240*795d594fSAndroid Build Coastguard Worker   }
241*795d594fSAndroid Build Coastguard Worker 
GetType()242*795d594fSAndroid Build Coastguard Worker   Type GetType() const {
243*795d594fSAndroid Build Coastguard Worker     return patch_type_;
244*795d594fSAndroid Build Coastguard Worker   }
245*795d594fSAndroid Build Coastguard Worker 
IntrinsicData()246*795d594fSAndroid Build Coastguard Worker   uint32_t IntrinsicData() const {
247*795d594fSAndroid Build Coastguard Worker     DCHECK(patch_type_ == Type::kIntrinsicReference);
248*795d594fSAndroid Build Coastguard Worker     return intrinsic_data_;
249*795d594fSAndroid Build Coastguard Worker   }
250*795d594fSAndroid Build Coastguard Worker 
BootImageOffset()251*795d594fSAndroid Build Coastguard Worker   uint32_t BootImageOffset() const {
252*795d594fSAndroid Build Coastguard Worker     DCHECK(patch_type_ == Type::kBootImageRelRo);
253*795d594fSAndroid Build Coastguard Worker     return boot_image_offset_;
254*795d594fSAndroid Build Coastguard Worker   }
255*795d594fSAndroid Build Coastguard Worker 
TargetMethod()256*795d594fSAndroid Build Coastguard Worker   MethodReference TargetMethod() const {
257*795d594fSAndroid Build Coastguard Worker     DCHECK(patch_type_ == Type::kMethodRelative ||
258*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kMethodAppImageRelRo ||
259*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kMethodBssEntry ||
260*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kJniEntrypointRelative ||
261*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kCallRelative);
262*795d594fSAndroid Build Coastguard Worker     return MethodReference(target_dex_file_, method_idx_);
263*795d594fSAndroid Build Coastguard Worker   }
264*795d594fSAndroid Build Coastguard Worker 
TargetType()265*795d594fSAndroid Build Coastguard Worker   TypeReference TargetType() const {
266*795d594fSAndroid Build Coastguard Worker     DCHECK(patch_type_ == Type::kTypeRelative ||
267*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kTypeAppImageRelRo ||
268*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kTypeBssEntry ||
269*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kPublicTypeBssEntry ||
270*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kPackageTypeBssEntry);
271*795d594fSAndroid Build Coastguard Worker     return TypeReference(target_dex_file_, dex::TypeIndex(type_idx_));
272*795d594fSAndroid Build Coastguard Worker   }
273*795d594fSAndroid Build Coastguard Worker 
TargetString()274*795d594fSAndroid Build Coastguard Worker   StringReference TargetString() const {
275*795d594fSAndroid Build Coastguard Worker     DCHECK(patch_type_ == Type::kStringRelative ||
276*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kStringBssEntry);
277*795d594fSAndroid Build Coastguard Worker     return StringReference(target_dex_file_, dex::StringIndex(string_idx_));
278*795d594fSAndroid Build Coastguard Worker   }
279*795d594fSAndroid Build Coastguard Worker 
TargetProto()280*795d594fSAndroid Build Coastguard Worker   ProtoReference TargetProto() const {
281*795d594fSAndroid Build Coastguard Worker     DCHECK(patch_type_ == Type::kMethodTypeBssEntry);
282*795d594fSAndroid Build Coastguard Worker     return ProtoReference(target_dex_file_, dex::ProtoIndex(proto_idx_));
283*795d594fSAndroid Build Coastguard Worker   }
284*795d594fSAndroid Build Coastguard Worker 
PcInsnOffset()285*795d594fSAndroid Build Coastguard Worker   uint32_t PcInsnOffset() const {
286*795d594fSAndroid Build Coastguard Worker     DCHECK(patch_type_ == Type::kIntrinsicReference ||
287*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kBootImageRelRo ||
288*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kMethodRelative ||
289*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kMethodAppImageRelRo ||
290*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kMethodBssEntry ||
291*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kJniEntrypointRelative ||
292*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kTypeRelative ||
293*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kTypeAppImageRelRo ||
294*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kTypeBssEntry ||
295*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kPublicTypeBssEntry ||
296*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kPackageTypeBssEntry ||
297*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kStringRelative ||
298*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kStringBssEntry ||
299*795d594fSAndroid Build Coastguard Worker            patch_type_ == Type::kMethodTypeBssEntry);
300*795d594fSAndroid Build Coastguard Worker     return pc_insn_offset_;
301*795d594fSAndroid Build Coastguard Worker   }
302*795d594fSAndroid Build Coastguard Worker 
EntrypointOffset()303*795d594fSAndroid Build Coastguard Worker   uint32_t EntrypointOffset() const {
304*795d594fSAndroid Build Coastguard Worker     DCHECK(patch_type_ == Type::kCallEntrypoint);
305*795d594fSAndroid Build Coastguard Worker     return entrypoint_offset_;
306*795d594fSAndroid Build Coastguard Worker   }
307*795d594fSAndroid Build Coastguard Worker 
GetBakerCustomValue1()308*795d594fSAndroid Build Coastguard Worker   uint32_t GetBakerCustomValue1() const {
309*795d594fSAndroid Build Coastguard Worker     DCHECK(patch_type_ == Type::kBakerReadBarrierBranch);
310*795d594fSAndroid Build Coastguard Worker     return baker_custom_value1_;
311*795d594fSAndroid Build Coastguard Worker   }
312*795d594fSAndroid Build Coastguard Worker 
GetBakerCustomValue2()313*795d594fSAndroid Build Coastguard Worker   uint32_t GetBakerCustomValue2() const {
314*795d594fSAndroid Build Coastguard Worker     DCHECK(patch_type_ == Type::kBakerReadBarrierBranch);
315*795d594fSAndroid Build Coastguard Worker     return baker_custom_value2_;
316*795d594fSAndroid Build Coastguard Worker   }
317*795d594fSAndroid Build Coastguard Worker 
318*795d594fSAndroid Build Coastguard Worker  private:
LinkerPatch(size_t literal_offset,Type patch_type,const DexFile * target_dex_file)319*795d594fSAndroid Build Coastguard Worker   LinkerPatch(size_t literal_offset, Type patch_type, const DexFile* target_dex_file)
320*795d594fSAndroid Build Coastguard Worker       : target_dex_file_(target_dex_file),
321*795d594fSAndroid Build Coastguard Worker         literal_offset_(literal_offset),
322*795d594fSAndroid Build Coastguard Worker         patch_type_(patch_type) {
323*795d594fSAndroid Build Coastguard Worker     cmp1_ = 0u;
324*795d594fSAndroid Build Coastguard Worker     cmp2_ = 0u;
325*795d594fSAndroid Build Coastguard Worker     // The compiler rejects methods that are too big, so the compiled code
326*795d594fSAndroid Build Coastguard Worker     // of a single method really shouln't be anywhere close to 16MiB.
327*795d594fSAndroid Build Coastguard Worker     DCHECK(IsUint<24>(literal_offset));
328*795d594fSAndroid Build Coastguard Worker   }
329*795d594fSAndroid Build Coastguard Worker 
330*795d594fSAndroid Build Coastguard Worker   const DexFile* target_dex_file_;
331*795d594fSAndroid Build Coastguard Worker   // TODO: Clean up naming. Some patched locations are literals but others are not.
332*795d594fSAndroid Build Coastguard Worker   uint32_t literal_offset_ : 24;  // Method code size up to 16MiB.
333*795d594fSAndroid Build Coastguard Worker   Type patch_type_ : 8;
334*795d594fSAndroid Build Coastguard Worker   union {
335*795d594fSAndroid Build Coastguard Worker     uint32_t cmp1_;               // Used for relational operators.
336*795d594fSAndroid Build Coastguard Worker     uint32_t boot_image_offset_;  // Data to write to the boot image .data.img.rel.ro entry.
337*795d594fSAndroid Build Coastguard Worker     uint32_t method_idx_;         // Method index for Call/Method patches.
338*795d594fSAndroid Build Coastguard Worker     uint32_t type_idx_;           // Type index for Type patches.
339*795d594fSAndroid Build Coastguard Worker     uint32_t string_idx_;         // String index for String patches.
340*795d594fSAndroid Build Coastguard Worker     uint32_t proto_idx_;          // Proto index for MethodType patches.
341*795d594fSAndroid Build Coastguard Worker     uint32_t intrinsic_data_;     // Data for IntrinsicObjects.
342*795d594fSAndroid Build Coastguard Worker     uint32_t entrypoint_offset_;  // Entrypoint offset in the Thread object.
343*795d594fSAndroid Build Coastguard Worker     uint32_t baker_custom_value1_;
344*795d594fSAndroid Build Coastguard Worker     static_assert(sizeof(method_idx_) == sizeof(cmp1_), "needed by relational operators");
345*795d594fSAndroid Build Coastguard Worker     static_assert(sizeof(type_idx_) == sizeof(cmp1_), "needed by relational operators");
346*795d594fSAndroid Build Coastguard Worker     static_assert(sizeof(string_idx_) == sizeof(cmp1_), "needed by relational operators");
347*795d594fSAndroid Build Coastguard Worker     static_assert(sizeof(proto_idx_) == sizeof(cmp1_), "needed by relational operators");
348*795d594fSAndroid Build Coastguard Worker     static_assert(sizeof(intrinsic_data_) == sizeof(cmp1_), "needed by relational operators");
349*795d594fSAndroid Build Coastguard Worker     static_assert(sizeof(baker_custom_value1_) == sizeof(cmp1_), "needed by relational operators");
350*795d594fSAndroid Build Coastguard Worker   };
351*795d594fSAndroid Build Coastguard Worker   union {
352*795d594fSAndroid Build Coastguard Worker     // Note: To avoid uninitialized padding on 64-bit systems, we use `size_t` for `cmp2_`.
353*795d594fSAndroid Build Coastguard Worker     // This allows a hashing function to treat an array of linker patches as raw memory.
354*795d594fSAndroid Build Coastguard Worker     size_t cmp2_;             // Used for relational operators.
355*795d594fSAndroid Build Coastguard Worker     // Literal offset of the insn loading PC (same as literal_offset if it's the same insn,
356*795d594fSAndroid Build Coastguard Worker     // may be different if the PC-relative addressing needs multiple insns).
357*795d594fSAndroid Build Coastguard Worker     uint32_t pc_insn_offset_;
358*795d594fSAndroid Build Coastguard Worker     uint32_t baker_custom_value2_;
359*795d594fSAndroid Build Coastguard Worker     static_assert(sizeof(pc_insn_offset_) <= sizeof(cmp2_), "needed by relational operators");
360*795d594fSAndroid Build Coastguard Worker     static_assert(sizeof(baker_custom_value2_) <= sizeof(cmp2_), "needed by relational operators");
361*795d594fSAndroid Build Coastguard Worker   };
362*795d594fSAndroid Build Coastguard Worker 
363*795d594fSAndroid Build Coastguard Worker   friend bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs);
364*795d594fSAndroid Build Coastguard Worker   friend bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs);
365*795d594fSAndroid Build Coastguard Worker };
366*795d594fSAndroid Build Coastguard Worker EXPORT std::ostream& operator<<(std::ostream& os, LinkerPatch::Type type);
367*795d594fSAndroid Build Coastguard Worker 
368*795d594fSAndroid Build Coastguard Worker inline bool operator==(const LinkerPatch& lhs, const LinkerPatch& rhs) {
369*795d594fSAndroid Build Coastguard Worker   return lhs.literal_offset_ == rhs.literal_offset_ &&
370*795d594fSAndroid Build Coastguard Worker       lhs.patch_type_ == rhs.patch_type_ &&
371*795d594fSAndroid Build Coastguard Worker       lhs.target_dex_file_ == rhs.target_dex_file_ &&
372*795d594fSAndroid Build Coastguard Worker       lhs.cmp1_ == rhs.cmp1_ &&
373*795d594fSAndroid Build Coastguard Worker       lhs.cmp2_ == rhs.cmp2_;
374*795d594fSAndroid Build Coastguard Worker }
375*795d594fSAndroid Build Coastguard Worker 
376*795d594fSAndroid Build Coastguard Worker inline bool operator<(const LinkerPatch& lhs, const LinkerPatch& rhs) {
377*795d594fSAndroid Build Coastguard Worker   return (lhs.literal_offset_ != rhs.literal_offset_) ? lhs.literal_offset_ < rhs.literal_offset_
378*795d594fSAndroid Build Coastguard Worker       : (lhs.patch_type_ != rhs.patch_type_) ? lhs.patch_type_ < rhs.patch_type_
379*795d594fSAndroid Build Coastguard Worker       : (lhs.target_dex_file_ != rhs.target_dex_file_) ? lhs.target_dex_file_ < rhs.target_dex_file_
380*795d594fSAndroid Build Coastguard Worker       : (lhs.cmp1_ != rhs.cmp1_) ? lhs.cmp1_ < rhs.cmp1_
381*795d594fSAndroid Build Coastguard Worker       : lhs.cmp2_ < rhs.cmp2_;
382*795d594fSAndroid Build Coastguard Worker }
383*795d594fSAndroid Build Coastguard Worker 
384*795d594fSAndroid Build Coastguard Worker }  // namespace linker
385*795d594fSAndroid Build Coastguard Worker }  // namespace art
386*795d594fSAndroid Build Coastguard Worker 
387*795d594fSAndroid Build Coastguard Worker #endif  // ART_COMPILER_LINKER_LINKER_PATCH_H_
388