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