diff options
31 files changed, 323 insertions, 29 deletions
diff --git a/compiler/linker/linker_patch.h b/compiler/linker/linker_patch.h index 19ee0e640c..b061e042f0 100644 --- a/compiler/linker/linker_patch.h +++ b/compiler/linker/linker_patch.h @@ -54,6 +54,7 @@ class LinkerPatch { kJniEntrypointRelative, kCallRelative, kTypeRelative, + kTypeAppImageRelRo, kTypeBssEntry, kPublicTypeBssEntry, kPackageTypeBssEntry, @@ -130,6 +131,16 @@ class LinkerPatch { return patch; } + static LinkerPatch TypeAppImageRelRoPatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t pc_insn_offset, + uint32_t target_type_idx) { + LinkerPatch patch(literal_offset, Type::kTypeAppImageRelRo, target_dex_file); + patch.type_idx_ = target_type_idx; + patch.pc_insn_offset_ = pc_insn_offset; + return patch; + } + static LinkerPatch TypeBssEntryPatch(size_t literal_offset, const DexFile* target_dex_file, uint32_t pc_insn_offset, @@ -241,6 +252,7 @@ class LinkerPatch { TypeReference TargetType() const { DCHECK(patch_type_ == Type::kTypeRelative || + patch_type_ == Type::kTypeAppImageRelRo || patch_type_ == Type::kTypeBssEntry || patch_type_ == Type::kPublicTypeBssEntry || patch_type_ == Type::kPackageTypeBssEntry); @@ -265,6 +277,7 @@ class LinkerPatch { patch_type_ == Type::kMethodBssEntry || patch_type_ == Type::kJniEntrypointRelative || patch_type_ == Type::kTypeRelative || + patch_type_ == Type::kTypeAppImageRelRo || patch_type_ == Type::kTypeBssEntry || patch_type_ == Type::kPublicTypeBssEntry || patch_type_ == Type::kPackageTypeBssEntry || diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index cfa28eda25..988809ee48 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -1011,6 +1011,7 @@ CodeGeneratorARM64::CodeGeneratorARM64(HGraph* graph, boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), + app_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), @@ -5155,6 +5156,13 @@ vixl::aarch64::Label* CodeGeneratorARM64::NewBootImageTypePatch( return NewPcRelativePatch(&dex_file, type_index.index_, adrp_label, &boot_image_type_patches_); } +vixl::aarch64::Label* CodeGeneratorARM64::NewAppImageTypePatch( + const DexFile& dex_file, + dex::TypeIndex type_index, + vixl::aarch64::Label* adrp_label) { + return NewPcRelativePatch(&dex_file, type_index.index_, adrp_label, &app_image_type_patches_); +} + vixl::aarch64::Label* CodeGeneratorARM64::NewBssEntryTypePatch( HLoadClass* load_class, vixl::aarch64::Label* adrp_label) { @@ -5365,6 +5373,7 @@ void CodeGeneratorARM64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* lin boot_image_method_patches_.size() + method_bss_entry_patches_.size() + boot_image_type_patches_.size() + + app_image_type_patches_.size() + type_bss_entry_patches_.size() + public_type_bss_entry_patches_.size() + package_type_bss_entry_patches_.size() + @@ -5387,12 +5396,15 @@ void CodeGeneratorARM64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* lin DCHECK(boot_image_type_patches_.empty()); DCHECK(boot_image_string_patches_.empty()); } + DCHECK_IMPLIES(!GetCompilerOptions().IsAppImage(), app_image_type_patches_.empty()); if (GetCompilerOptions().IsBootImage()) { EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::IntrinsicReferencePatch>>( boot_image_other_patches_, linker_patches); } else { EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::BootImageRelRoPatch>>( boot_image_other_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeAppImageRelRoPatch>( + app_image_type_patches_, linker_patches); } EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>( method_bss_entry_patches_, linker_patches); @@ -5504,6 +5516,7 @@ HLoadClass::LoadKind CodeGeneratorARM64::GetSupportedLoadClassKind( break; case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: case HLoadClass::LoadKind::kBootImageRelRo: + case HLoadClass::LoadKind::kAppImageRelRo: case HLoadClass::LoadKind::kBssEntry: case HLoadClass::LoadKind::kBssEntryPublic: case HLoadClass::LoadKind::kBssEntryPackage: @@ -5613,6 +5626,20 @@ void InstructionCodeGeneratorARM64::VisitLoadClass(HLoadClass* cls) NO_THREAD_SA codegen_->LoadBootImageRelRoEntry(out.W(), boot_image_offset); break; } + case HLoadClass::LoadKind::kAppImageRelRo: { + DCHECK(codegen_->GetCompilerOptions().IsAppImage()); + DCHECK_EQ(read_barrier_option, kWithoutReadBarrier); + // Add ADRP with its PC-relative type patch. + const DexFile& dex_file = cls->GetDexFile(); + dex::TypeIndex type_index = cls->GetTypeIndex(); + vixl::aarch64::Label* adrp_label = codegen_->NewAppImageTypePatch(dex_file, type_index); + codegen_->EmitAdrpPlaceholder(adrp_label, out.X()); + // Add LDR with its PC-relative type patch. + vixl::aarch64::Label* ldr_label = + codegen_->NewAppImageTypePatch(dex_file, type_index, adrp_label); + codegen_->EmitLdrOffsetPlaceholder(ldr_label, out.W(), out.X()); + break; + } case HLoadClass::LoadKind::kBssEntry: case HLoadClass::LoadKind::kBssEntryPublic: case HLoadClass::LoadKind::kBssEntryPackage: { diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h index 32a69a9df7..78049c5675 100644 --- a/compiler/optimizing/code_generator_arm64.h +++ b/compiler/optimizing/code_generator_arm64.h @@ -817,6 +817,14 @@ class CodeGeneratorARM64 : public CodeGenerator { dex::TypeIndex type_index, vixl::aarch64::Label* adrp_label = nullptr); + // Add a new app image type patch for an instruction and return the label + // to be bound before the instruction. The instruction will be either the + // ADRP (pass `adrp_label = null`) or the LDR (pass `adrp_label` pointing + // to the associated ADRP patch label). + vixl::aarch64::Label* NewAppImageTypePatch(const DexFile& dex_file, + dex::TypeIndex type_index, + vixl::aarch64::Label* adrp_label = nullptr); + // Add a new .bss entry type patch for an instruction and return the label // to be bound before the instruction. The instruction will be either the // ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing @@ -1150,6 +1158,8 @@ class CodeGeneratorARM64 : public CodeGenerator { ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_; // PC-relative type patch info for kBootImageLinkTimePcRelative. ArenaDeque<PcRelativePatchInfo> boot_image_type_patches_; + // PC-relative type patch info for kAppImageRelRo. + ArenaDeque<PcRelativePatchInfo> app_image_type_patches_; // PC-relative type patch info for kBssEntry. ArenaDeque<PcRelativePatchInfo> type_bss_entry_patches_; // PC-relative public type patch info for kBssEntryPublic. diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc index a7cc5a6d12..7c1a9b21f2 100644 --- a/compiler/optimizing/code_generator_arm_vixl.cc +++ b/compiler/optimizing/code_generator_arm_vixl.cc @@ -1946,6 +1946,7 @@ CodeGeneratorARMVIXL::CodeGeneratorARMVIXL(HGraph* graph, boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), + app_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), @@ -7657,6 +7658,7 @@ HLoadClass::LoadKind CodeGeneratorARMVIXL::GetSupportedLoadClassKind( break; case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: case HLoadClass::LoadKind::kBootImageRelRo: + case HLoadClass::LoadKind::kAppImageRelRo: case HLoadClass::LoadKind::kBssEntry: case HLoadClass::LoadKind::kBssEntryPublic: case HLoadClass::LoadKind::kBssEntryPackage: @@ -7760,6 +7762,15 @@ void InstructionCodeGeneratorARMVIXL::VisitLoadClass(HLoadClass* cls) NO_THREAD_ codegen_->LoadBootImageRelRoEntry(out, boot_image_offset); break; } + case HLoadClass::LoadKind::kAppImageRelRo: { + DCHECK(codegen_->GetCompilerOptions().IsAppImage()); + DCHECK_EQ(read_barrier_option, kWithoutReadBarrier); + CodeGeneratorARMVIXL::PcRelativePatchInfo* labels = + codegen_->NewAppImageTypePatch(cls->GetDexFile(), cls->GetTypeIndex()); + codegen_->EmitMovwMovtPlaceholder(labels, out); + __ Ldr(out, MemOperand(out, /*offset=*/ 0)); + break; + } case HLoadClass::LoadKind::kBssEntry: case HLoadClass::LoadKind::kBssEntryPublic: case HLoadClass::LoadKind::kBssEntryPackage: { @@ -9691,6 +9702,11 @@ CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewBootImageTyp return NewPcRelativePatch(&dex_file, type_index.index_, &boot_image_type_patches_); } +CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewAppImageTypePatch( + const DexFile& dex_file, dex::TypeIndex type_index) { + return NewPcRelativePatch(&dex_file, type_index.index_, &app_image_type_patches_); +} + CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewTypeBssEntryPatch( HLoadClass* load_class) { const DexFile& dex_file = load_class->GetDexFile(); @@ -9877,6 +9893,7 @@ void CodeGeneratorARMVIXL::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* l /* MOVW+MOVT for each entry */ 2u * boot_image_method_patches_.size() + /* MOVW+MOVT for each entry */ 2u * method_bss_entry_patches_.size() + /* MOVW+MOVT for each entry */ 2u * boot_image_type_patches_.size() + + /* MOVW+MOVT for each entry */ 2u * app_image_type_patches_.size() + /* MOVW+MOVT for each entry */ 2u * type_bss_entry_patches_.size() + /* MOVW+MOVT for each entry */ 2u * public_type_bss_entry_patches_.size() + /* MOVW+MOVT for each entry */ 2u * package_type_bss_entry_patches_.size() + @@ -9898,12 +9915,15 @@ void CodeGeneratorARMVIXL::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* l DCHECK(boot_image_type_patches_.empty()); DCHECK(boot_image_string_patches_.empty()); } + DCHECK_IMPLIES(!GetCompilerOptions().IsAppImage(), app_image_type_patches_.empty()); if (GetCompilerOptions().IsBootImage()) { EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::IntrinsicReferencePatch>>( boot_image_other_patches_, linker_patches); } else { EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::BootImageRelRoPatch>>( boot_image_other_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeAppImageRelRoPatch>( + app_image_type_patches_, linker_patches); } EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>( method_bss_entry_patches_, linker_patches); diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h index a62097d08f..51bee1cd77 100644 --- a/compiler/optimizing/code_generator_arm_vixl.h +++ b/compiler/optimizing/code_generator_arm_vixl.h @@ -709,6 +709,7 @@ class CodeGeneratorARMVIXL : public CodeGenerator { PcRelativePatchInfo* NewBootImageMethodPatch(MethodReference target_method); PcRelativePatchInfo* NewMethodBssEntryPatch(MethodReference target_method); PcRelativePatchInfo* NewBootImageTypePatch(const DexFile& dex_file, dex::TypeIndex type_index); + PcRelativePatchInfo* NewAppImageTypePatch(const DexFile& dex_file, dex::TypeIndex type_index); PcRelativePatchInfo* NewTypeBssEntryPatch(HLoadClass* load_class); PcRelativePatchInfo* NewBootImageStringPatch(const DexFile& dex_file, dex::StringIndex string_index); @@ -1029,6 +1030,8 @@ class CodeGeneratorARMVIXL : public CodeGenerator { ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_; // PC-relative type patch info for kBootImageLinkTimePcRelative. ArenaDeque<PcRelativePatchInfo> boot_image_type_patches_; + // PC-relative type patch info for kAppImageRelRo. + ArenaDeque<PcRelativePatchInfo> app_image_type_patches_; // PC-relative type patch info for kBssEntry. ArenaDeque<PcRelativePatchInfo> type_bss_entry_patches_; // PC-relative public type patch info for kBssEntryPublic. diff --git a/compiler/optimizing/code_generator_riscv64.cc b/compiler/optimizing/code_generator_riscv64.cc index 29594e94c1..9b499a08a2 100644 --- a/compiler/optimizing/code_generator_riscv64.cc +++ b/compiler/optimizing/code_generator_riscv64.cc @@ -4373,6 +4373,18 @@ void InstructionCodeGeneratorRISCV64::VisitLoadClass(HLoadClass* instruction) codegen_->LoadBootImageRelRoEntry(out, boot_image_offset); break; } + case HLoadClass::LoadKind::kAppImageRelRo: { + DCHECK(codegen_->GetCompilerOptions().IsAppImage()); + DCHECK_EQ(read_barrier_option, kWithoutReadBarrier); + CodeGeneratorRISCV64::PcRelativePatchInfo* info_high = + codegen_->NewAppImageTypePatch(instruction->GetDexFile(), instruction->GetTypeIndex()); + codegen_->EmitPcRelativeAuipcPlaceholder(info_high, out); + CodeGeneratorRISCV64::PcRelativePatchInfo* info_low = + codegen_->NewAppImageTypePatch( + instruction->GetDexFile(), instruction->GetTypeIndex(), info_high); + codegen_->EmitPcRelativeLwuPlaceholder(info_low, out, out); + break; + } case HLoadClass::LoadKind::kBssEntry: case HLoadClass::LoadKind::kBssEntryPublic: case HLoadClass::LoadKind::kBssEntryPackage: { @@ -5820,6 +5832,7 @@ CodeGeneratorRISCV64::CodeGeneratorRISCV64(HGraph* graph, boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), + app_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), @@ -6428,6 +6441,7 @@ HLoadClass::LoadKind CodeGeneratorRISCV64::GetSupportedLoadClassKind( break; case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: case HLoadClass::LoadKind::kBootImageRelRo: + case HLoadClass::LoadKind::kAppImageRelRo: case HLoadClass::LoadKind::kBssEntry: case HLoadClass::LoadKind::kBssEntryPublic: case HLoadClass::LoadKind::kBssEntryPackage: @@ -6479,6 +6493,11 @@ CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewBootImageTyp return NewPcRelativePatch(&dex_file, type_index.index_, info_high, &boot_image_type_patches_); } +CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewAppImageTypePatch( + const DexFile& dex_file, dex::TypeIndex type_index, const PcRelativePatchInfo* info_high) { + return NewPcRelativePatch(&dex_file, type_index.index_, info_high, &app_image_type_patches_); +} + CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewBootImageJniEntrypointPatch( MethodReference target_method, const PcRelativePatchInfo* info_high) { return NewPcRelativePatch( @@ -6642,6 +6661,7 @@ void CodeGeneratorRISCV64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* l boot_image_method_patches_.size() + method_bss_entry_patches_.size() + boot_image_type_patches_.size() + + app_image_type_patches_.size() + type_bss_entry_patches_.size() + public_type_bss_entry_patches_.size() + package_type_bss_entry_patches_.size() + @@ -6662,12 +6682,15 @@ void CodeGeneratorRISCV64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* l DCHECK(boot_image_type_patches_.empty()); DCHECK(boot_image_string_patches_.empty()); } + DCHECK_IMPLIES(!GetCompilerOptions().IsAppImage(), app_image_type_patches_.empty()); if (GetCompilerOptions().IsBootImage()) { EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::IntrinsicReferencePatch>>( boot_image_other_patches_, linker_patches); } else { EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::BootImageRelRoPatch>>( boot_image_other_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeAppImageRelRoPatch>( + app_image_type_patches_, linker_patches); } EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>( method_bss_entry_patches_, linker_patches); diff --git a/compiler/optimizing/code_generator_riscv64.h b/compiler/optimizing/code_generator_riscv64.h index 7f4f352341..227882e7b8 100644 --- a/compiler/optimizing/code_generator_riscv64.h +++ b/compiler/optimizing/code_generator_riscv64.h @@ -589,6 +589,9 @@ class CodeGeneratorRISCV64 : public CodeGenerator { PcRelativePatchInfo* NewBootImageTypePatch(const DexFile& dex_file, dex::TypeIndex type_index, const PcRelativePatchInfo* info_high = nullptr); + PcRelativePatchInfo* NewAppImageTypePatch(const DexFile& dex_file, + dex::TypeIndex type_index, + const PcRelativePatchInfo* info_high = nullptr); PcRelativePatchInfo* NewTypeBssEntryPatch(HLoadClass* load_class, const PcRelativePatchInfo* info_high = nullptr); PcRelativePatchInfo* NewBootImageStringPatch(const DexFile& dex_file, @@ -819,6 +822,8 @@ class CodeGeneratorRISCV64 : public CodeGenerator { ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_; // PC-relative type patch info for kBootImageLinkTimePcRelative. ArenaDeque<PcRelativePatchInfo> boot_image_type_patches_; + // PC-relative type patch info for kAppImageRelRo. + ArenaDeque<PcRelativePatchInfo> app_image_type_patches_; // PC-relative type patch info for kBssEntry. ArenaDeque<PcRelativePatchInfo> type_bss_entry_patches_; // PC-relative public type patch info for kBssEntryPublic. diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 5ad818dd53..4329e40efc 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -1173,6 +1173,7 @@ CodeGeneratorX86::CodeGeneratorX86(HGraph* graph, boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), + app_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), @@ -5715,6 +5716,14 @@ void CodeGeneratorX86::RecordBootImageTypePatch(HLoadClass* load_class) { __ Bind(&boot_image_type_patches_.back().label); } +void CodeGeneratorX86::RecordAppImageTypePatch(HLoadClass* load_class) { + HX86ComputeBaseMethodAddress* method_address = + load_class->InputAt(0)->AsX86ComputeBaseMethodAddress(); + app_image_type_patches_.emplace_back( + method_address, &load_class->GetDexFile(), load_class->GetTypeIndex().index_); + __ Bind(&app_image_type_patches_.back().label); +} + Label* CodeGeneratorX86::NewTypeBssEntryPatch(HLoadClass* load_class) { HX86ComputeBaseMethodAddress* method_address = load_class->InputAt(0)->AsX86ComputeBaseMethodAddress(); @@ -5844,6 +5853,7 @@ void CodeGeneratorX86::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linke boot_image_method_patches_.size() + method_bss_entry_patches_.size() + boot_image_type_patches_.size() + + app_image_type_patches_.size() + type_bss_entry_patches_.size() + public_type_bss_entry_patches_.size() + package_type_bss_entry_patches_.size() + @@ -5864,12 +5874,15 @@ void CodeGeneratorX86::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linke DCHECK(boot_image_type_patches_.empty()); DCHECK(boot_image_string_patches_.empty()); } + DCHECK_IMPLIES(!GetCompilerOptions().IsAppImage(), app_image_type_patches_.empty()); if (GetCompilerOptions().IsBootImage()) { EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::IntrinsicReferencePatch>>( boot_image_other_patches_, linker_patches); } else { EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::BootImageRelRoPatch>>( boot_image_other_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeAppImageRelRoPatch>( + app_image_type_patches_, linker_patches); } EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>( method_bss_entry_patches_, linker_patches); @@ -7283,6 +7296,7 @@ HLoadClass::LoadKind CodeGeneratorX86::GetSupportedLoadClassKind( break; case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: case HLoadClass::LoadKind::kBootImageRelRo: + case HLoadClass::LoadKind::kAppImageRelRo: case HLoadClass::LoadKind::kBssEntry: case HLoadClass::LoadKind::kBssEntryPublic: case HLoadClass::LoadKind::kBssEntryPackage: @@ -7396,6 +7410,14 @@ void InstructionCodeGeneratorX86::VisitLoadClass(HLoadClass* cls) NO_THREAD_SAFE CodeGenerator::GetBootImageOffset(cls)); break; } + case HLoadClass::LoadKind::kAppImageRelRo: { + DCHECK(codegen_->GetCompilerOptions().IsAppImage()); + DCHECK_EQ(read_barrier_option, kWithoutReadBarrier); + Register method_address = locations->InAt(0).AsRegister<Register>(); + __ movl(out, Address(method_address, CodeGeneratorX86::kPlaceholder32BitOffset)); + codegen_->RecordAppImageTypePatch(cls); + break; + } case HLoadClass::LoadKind::kBssEntry: case HLoadClass::LoadKind::kBssEntryPublic: case HLoadClass::LoadKind::kBssEntryPackage: { diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h index ee87947ca0..93f8e6ed9b 100644 --- a/compiler/optimizing/code_generator_x86.h +++ b/compiler/optimizing/code_generator_x86.h @@ -539,6 +539,7 @@ class CodeGeneratorX86 : public CodeGenerator { void RecordBootImageMethodPatch(HInvoke* invoke); void RecordMethodBssEntryPatch(HInvoke* invoke); void RecordBootImageTypePatch(HLoadClass* load_class); + void RecordAppImageTypePatch(HLoadClass* load_class); Label* NewTypeBssEntryPatch(HLoadClass* load_class); void RecordBootImageStringPatch(HLoadString* load_string); Label* NewStringBssEntryPatch(HLoadString* load_string); @@ -775,6 +776,8 @@ class CodeGeneratorX86 : public CodeGenerator { ArenaDeque<X86PcRelativePatchInfo> method_bss_entry_patches_; // PC-relative type patch info for kBootImageLinkTimePcRelative. ArenaDeque<X86PcRelativePatchInfo> boot_image_type_patches_; + // PC-relative type patch info for kAppImageRelRo. + ArenaDeque<X86PcRelativePatchInfo> app_image_type_patches_; // PC-relative type patch info for kBssEntry. ArenaDeque<X86PcRelativePatchInfo> type_bss_entry_patches_; // PC-relative public type patch info for kBssEntryPublic. diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 4855b086ae..5b4f1b8b25 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -1328,6 +1328,12 @@ void CodeGeneratorX86_64::RecordBootImageTypePatch(const DexFile& dex_file, __ Bind(&boot_image_type_patches_.back().label); } +void CodeGeneratorX86_64::RecordAppImageTypePatch(const DexFile& dex_file, + dex::TypeIndex type_index) { + app_image_type_patches_.emplace_back(&dex_file, type_index.index_); + __ Bind(&app_image_type_patches_.back().label); +} + Label* CodeGeneratorX86_64::NewTypeBssEntryPatch(HLoadClass* load_class) { ArenaDeque<PatchInfo<Label>>* patches = nullptr; switch (load_class->GetLoadKind()) { @@ -1448,6 +1454,7 @@ void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* li boot_image_method_patches_.size() + method_bss_entry_patches_.size() + boot_image_type_patches_.size() + + app_image_type_patches_.size() + type_bss_entry_patches_.size() + public_type_bss_entry_patches_.size() + package_type_bss_entry_patches_.size() + @@ -1469,12 +1476,15 @@ void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* li DCHECK(boot_image_type_patches_.empty()); DCHECK(boot_image_string_patches_.empty()); } + DCHECK_IMPLIES(!GetCompilerOptions().IsAppImage(), app_image_type_patches_.empty()); if (GetCompilerOptions().IsBootImage()) { EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::IntrinsicReferencePatch>>( boot_image_other_patches_, linker_patches); } else { EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::BootImageRelRoPatch>>( boot_image_other_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeAppImageRelRoPatch>( + app_image_type_patches_, linker_patches); } EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>( method_bss_entry_patches_, linker_patches); @@ -1607,6 +1617,7 @@ CodeGeneratorX86_64::CodeGeneratorX86_64(HGraph* graph, boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), + app_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), @@ -6620,6 +6631,7 @@ HLoadClass::LoadKind CodeGeneratorX86_64::GetSupportedLoadClassKind( break; case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: case HLoadClass::LoadKind::kBootImageRelRo: + case HLoadClass::LoadKind::kAppImageRelRo: case HLoadClass::LoadKind::kBssEntry: case HLoadClass::LoadKind::kBssEntryPublic: case HLoadClass::LoadKind::kBssEntryPackage: @@ -6732,6 +6744,14 @@ void InstructionCodeGeneratorX86_64::VisitLoadClass(HLoadClass* cls) NO_THREAD_S codegen_->RecordBootImageRelRoPatch(CodeGenerator::GetBootImageOffset(cls)); break; } + case HLoadClass::LoadKind::kAppImageRelRo: { + DCHECK(codegen_->GetCompilerOptions().IsAppImage()); + DCHECK_EQ(read_barrier_option, kWithoutReadBarrier); + __ movl(out, + Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset, /* no_rip= */ false)); + codegen_->RecordAppImageTypePatch(cls->GetDexFile(), cls->GetTypeIndex()); + break; + } case HLoadClass::LoadKind::kBssEntry: case HLoadClass::LoadKind::kBssEntryPublic: case HLoadClass::LoadKind::kBssEntryPackage: { diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h index b8e2456381..7a5e4aa894 100644 --- a/compiler/optimizing/code_generator_x86_64.h +++ b/compiler/optimizing/code_generator_x86_64.h @@ -532,6 +532,7 @@ class CodeGeneratorX86_64 : public CodeGenerator { void RecordBootImageMethodPatch(HInvoke* invoke); void RecordMethodBssEntryPatch(HInvoke* invoke); void RecordBootImageTypePatch(const DexFile& dex_file, dex::TypeIndex type_index); + void RecordAppImageTypePatch(const DexFile& dex_file, dex::TypeIndex type_index); Label* NewTypeBssEntryPatch(HLoadClass* load_class); void RecordBootImageStringPatch(HLoadString* load_string); Label* NewStringBssEntryPatch(HLoadString* load_string); @@ -738,6 +739,8 @@ class CodeGeneratorX86_64 : public CodeGenerator { ArenaDeque<PatchInfo<Label>> method_bss_entry_patches_; // PC-relative type patch info for kBootImageLinkTimePcRelative. ArenaDeque<PatchInfo<Label>> boot_image_type_patches_; + // PC-relative type patch info for kAppImageRelRo. + ArenaDeque<PatchInfo<Label>> app_image_type_patches_; // PC-relative type patch info for kBssEntry. ArenaDeque<PatchInfo<Label>> type_bss_entry_patches_; // PC-relative public type patch info for kBssEntryPublic. diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 90fc5db02e..33ffc07ba8 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -6743,6 +6743,10 @@ class HLoadClass final : public HInstruction { // Used for boot image classes referenced by apps in AOT-compiled code. kBootImageRelRo, + // Load from an app image entry in the .data.img.rel.ro using a PC-relative load. + // Used for app image classes referenced by apps in AOT-compiled code. + kAppImageRelRo, + // Load from an entry in the .bss section using a PC-relative load. // Used for classes outside boot image referenced by AOT-compiled app and boot image code. kBssEntry, @@ -6814,6 +6818,7 @@ class HLoadClass final : public HInstruction { bool HasPcRelativeLoadKind() const { return GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative || GetLoadKind() == LoadKind::kBootImageRelRo || + GetLoadKind() == LoadKind::kAppImageRelRo || GetLoadKind() == LoadKind::kBssEntry || GetLoadKind() == LoadKind::kBssEntryPublic || GetLoadKind() == LoadKind::kBssEntryPackage; @@ -6933,6 +6938,7 @@ class HLoadClass final : public HInstruction { static bool HasTypeReference(LoadKind load_kind) { return load_kind == LoadKind::kReferrersClass || load_kind == LoadKind::kBootImageLinkTimePcRelative || + load_kind == LoadKind::kAppImageRelRo || load_kind == LoadKind::kBssEntry || load_kind == LoadKind::kBssEntryPublic || load_kind == LoadKind::kBssEntryPackage || @@ -6978,6 +6984,7 @@ inline void HLoadClass::AddSpecialInput(HInstruction* special_input) { // including literal pool loads, which are PC-relative too. DCHECK(GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative || GetLoadKind() == LoadKind::kBootImageRelRo || + GetLoadKind() == LoadKind::kAppImageRelRo || GetLoadKind() == LoadKind::kBssEntry || GetLoadKind() == LoadKind::kBssEntryPublic || GetLoadKind() == LoadKind::kBssEntryPackage || diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc index aa75c2464b..cb94491b8e 100644 --- a/compiler/optimizing/sharpening.cc +++ b/compiler/optimizing/sharpening.cc @@ -277,7 +277,7 @@ HLoadClass::LoadKind HSharpening::ComputeLoadClassKind( } else if (compiler_options.IsAppImage() && is_class_in_current_image()) { // AOT app compilation, app image class. is_in_image = true; - desired_load_kind = HLoadClass::LoadKind::kBssEntry; + desired_load_kind = HLoadClass::LoadKind::kAppImageRelRo; } else { // Not JIT and the klass is not in boot image or app image. desired_load_kind = HLoadClass::LoadKind::kBssEntry; diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 9f2d263de3..9529e6d28b 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -2130,6 +2130,7 @@ class Dex2Oat final { elf_writer->PrepareDynamicSection(oat_writer->GetOatHeader().GetExecutableOffset(), oat_writer->GetCodeSize(), oat_writer->GetDataImgRelRoSize(), + oat_writer->GetDataImgRelRoAppImageOffset(), oat_writer->GetBssSize(), oat_writer->GetBssMethodsOffset(), oat_writer->GetBssRootsOffset(), diff --git a/dex2oat/linker/arm64/relative_patcher_arm64.cc b/dex2oat/linker/arm64/relative_patcher_arm64.cc index 8772974c4b..2956285545 100644 --- a/dex2oat/linker/arm64/relative_patcher_arm64.cc +++ b/dex2oat/linker/arm64/relative_patcher_arm64.cc @@ -66,6 +66,7 @@ inline bool IsAdrpPatch(const LinkerPatch& patch) { case LinkerPatch::Type::kMethodBssEntry: case LinkerPatch::Type::kJniEntrypointRelative: case LinkerPatch::Type::kTypeRelative: + case LinkerPatch::Type::kTypeAppImageRelRo: case LinkerPatch::Type::kTypeBssEntry: case LinkerPatch::Type::kPublicTypeBssEntry: case LinkerPatch::Type::kPackageTypeBssEntry: @@ -274,6 +275,7 @@ void Arm64RelativePatcher::PatchPcRelativeReference(std::vector<uint8_t>* code, DCHECK(patch.GetType() == LinkerPatch::Type::kBootImageRelRo || patch.GetType() == LinkerPatch::Type::kMethodBssEntry || patch.GetType() == LinkerPatch::Type::kJniEntrypointRelative || + patch.GetType() == LinkerPatch::Type::kTypeAppImageRelRo || patch.GetType() == LinkerPatch::Type::kTypeBssEntry || patch.GetType() == LinkerPatch::Type::kPublicTypeBssEntry || patch.GetType() == LinkerPatch::Type::kPackageTypeBssEntry || diff --git a/dex2oat/linker/elf_writer.h b/dex2oat/linker/elf_writer.h index a1d0ece9de..35e3565592 100644 --- a/dex2oat/linker/elf_writer.h +++ b/dex2oat/linker/elf_writer.h @@ -61,6 +61,7 @@ class ElfWriter { virtual void PrepareDynamicSection(size_t rodata_size, size_t text_size, size_t data_img_rel_ro_size, + size_t data_img_rel_ro_app_image_offset, size_t bss_size, size_t bss_methods_offset, size_t bss_roots_offset, diff --git a/dex2oat/linker/elf_writer_quick.cc b/dex2oat/linker/elf_writer_quick.cc index 373c46ce2c..f87ca6d81e 100644 --- a/dex2oat/linker/elf_writer_quick.cc +++ b/dex2oat/linker/elf_writer_quick.cc @@ -92,6 +92,7 @@ class ElfWriterQuick final : public ElfWriter { void PrepareDynamicSection(size_t rodata_size, size_t text_size, size_t data_img_rel_ro_size, + size_t data_img_rel_ro_app_image_offset, size_t bss_size, size_t bss_methods_offset, size_t bss_roots_offset, @@ -173,6 +174,7 @@ template <typename ElfTypes> void ElfWriterQuick<ElfTypes>::PrepareDynamicSection(size_t rodata_size, size_t text_size, size_t data_img_rel_ro_size, + size_t data_img_rel_ro_app_image_offset, size_t bss_size, size_t bss_methods_offset, size_t bss_roots_offset, @@ -191,6 +193,7 @@ void ElfWriterQuick<ElfTypes>::PrepareDynamicSection(size_t rodata_size, rodata_size_, text_size_, data_img_rel_ro_size_, + data_img_rel_ro_app_image_offset, bss_size_, bss_methods_offset, bss_roots_offset, diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h index 9f553c1c74..f4a87bb84d 100644 --- a/dex2oat/linker/image_test.h +++ b/dex2oat/linker/image_test.h @@ -309,6 +309,7 @@ inline void ImageTest::DoCompile(ImageHeader::StorageMode storage_mode, elf_writer->PrepareDynamicSection(oat_writer->GetOatHeader().GetExecutableOffset(), oat_writer->GetCodeSize(), oat_writer->GetDataImgRelRoSize(), + oat_writer->GetDataImgRelRoAppImageOffset(), oat_writer->GetBssSize(), oat_writer->GetBssMethodsOffset(), oat_writer->GetBssRootsOffset(), diff --git a/dex2oat/linker/image_writer.h b/dex2oat/linker/image_writer.h index 4d45529871..8ffe226bec 100644 --- a/dex2oat/linker/image_writer.h +++ b/dex2oat/linker/image_writer.h @@ -128,6 +128,15 @@ class ImageWriter final { } } + uint32_t GetGlobalImageOffset(mirror::Object* object) const REQUIRES_SHARED(Locks::mutator_lock_) { + DCHECK(object != nullptr); + DCHECK(!IsInBootImage(object)); + size_t oat_index = GetOatIndex(object); + const ImageInfo& image_info = GetImageInfo(oat_index); + return dchecked_integral_cast<uint32_t>( + image_info.image_begin_ + GetImageOffset(object, oat_index) - global_image_begin_); + } + ArtMethod* GetImageMethodAddress(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_); const void* GetIntrinsicReferenceAddress(uint32_t intrinsic_data) REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc index b1287d9ab3..7c2f8d6249 100644 --- a/dex2oat/linker/oat_writer.cc +++ b/dex2oat/linker/oat_writer.cc @@ -373,6 +373,7 @@ OatWriter::OatWriter(const CompilerOptions& compiler_options, oat_size_(0u), data_img_rel_ro_start_(0u), data_img_rel_ro_size_(0u), + data_img_rel_ro_app_image_offset_(0u), bss_start_(0u), bss_size_(0u), bss_methods_offset_(0u), @@ -380,6 +381,7 @@ OatWriter::OatWriter(const CompilerOptions& compiler_options, boot_image_rel_ro_entries_(), bss_method_entry_references_(), bss_method_entries_(), + app_image_rel_ro_type_entries_(), bss_type_entries_(), bss_public_type_entries_(), bss_package_type_entries_(), @@ -754,6 +756,9 @@ class OatWriter::InitBssLayoutMethodVisitor : public DexMethodVisitor { target_method.dex_file->NumMethodIds(), &writer_->bss_method_entry_references_); writer_->bss_method_entries_.Overwrite(target_method, /* placeholder */ 0u); + } else if (patch.GetType() == LinkerPatch::Type::kTypeAppImageRelRo) { + writer_->app_image_rel_ro_type_entries_.Overwrite(patch.TargetType(), + /* placeholder */ 0u); } else if (patch.GetType() == LinkerPatch::Type::kTypeBssEntry) { TypeReference target_type = patch.TargetType(); AddBssReference(target_type, @@ -1710,6 +1715,16 @@ class OatWriter::WriteCodeMethodVisitor : public OrderedMethodVisitor { target_offset); break; } + case LinkerPatch::Type::kTypeAppImageRelRo: { + uint32_t target_offset = + writer_->data_img_rel_ro_start_ + + writer_->app_image_rel_ro_type_entries_.Get(patch.TargetType()); + writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, + patch, + offset_ + literal_offset, + target_offset); + break; + } case LinkerPatch::Type::kTypeBssEntry: { uint32_t target_offset = writer_->bss_start_ + writer_->bss_type_entries_.Get(patch.TargetType()); @@ -2364,7 +2379,7 @@ size_t OatWriter::InitOatCodeDexFiles(size_t offset) { size_t OatWriter::InitDataImgRelRoLayout(size_t offset) { DCHECK_EQ(data_img_rel_ro_size_, 0u); - if (boot_image_rel_ro_entries_.empty()) { + if (boot_image_rel_ro_entries_.empty() && app_image_rel_ro_type_entries_.empty()) { // Nothing to put to the .data.img.rel.ro section. return offset; } @@ -2377,6 +2392,14 @@ size_t OatWriter::InitDataImgRelRoLayout(size_t offset) { data_img_rel_ro_size_ += sizeof(uint32_t); } + data_img_rel_ro_app_image_offset_ = data_img_rel_ro_size_; + + for (auto& entry : app_image_rel_ro_type_entries_) { + size_t& entry_offset = entry.second; + entry_offset = data_img_rel_ro_size_; + data_img_rel_ro_size_ += sizeof(uint32_t); + } + offset = data_img_rel_ro_start_ + data_img_rel_ro_size_; return offset; } @@ -3177,18 +3200,39 @@ size_t OatWriter::WriteCodeDexFiles(OutputStream* out, size_t OatWriter::WriteDataImgRelRo(OutputStream* out, size_t file_offset, size_t relative_offset) { - if (boot_image_rel_ro_entries_.empty()) { + if (boot_image_rel_ro_entries_.empty() && app_image_rel_ro_type_entries_.empty()) { return relative_offset; } // Write the entire .data.img.rel.ro with a single WriteFully(). std::vector<uint32_t> data; - data.reserve(boot_image_rel_ro_entries_.size()); + data.reserve(boot_image_rel_ro_entries_.size() + app_image_rel_ro_type_entries_.size()); for (const auto& entry : boot_image_rel_ro_entries_) { uint32_t boot_image_offset = entry.first; data.push_back(boot_image_offset); } - DCHECK_EQ(data.size(), boot_image_rel_ro_entries_.size()); + if (!app_image_rel_ro_type_entries_.empty()) { + DCHECK(GetCompilerOptions().IsAppImage()); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + ScopedObjectAccess soa(Thread::Current()); + const DexFile* last_dex_file = nullptr; + ObjPtr<mirror::DexCache> dex_cache = nullptr; + ObjPtr<mirror::ClassLoader> class_loader = nullptr; + for (const auto& entry : app_image_rel_ro_type_entries_) { + TypeReference target_type = entry.first; + if (target_type.dex_file != last_dex_file) { + dex_cache = class_linker->FindDexCache(soa.Self(), *target_type.dex_file); + class_loader = dex_cache->GetClassLoader(); + last_dex_file = target_type.dex_file; + } + ObjPtr<mirror::Class> type = + class_linker->LookupResolvedType(target_type.TypeIndex(), dex_cache, class_loader); + CHECK(type != nullptr); + uint32_t app_image_offset = image_writer_->GetGlobalImageOffset(type.Ptr()); + data.push_back(app_image_offset); + } + } + DCHECK_EQ(data.size(), boot_image_rel_ro_entries_.size() + app_image_rel_ro_type_entries_.size()); DCHECK_OFFSET(); if (!out->WriteFully(data.data(), data.size() * sizeof(data[0]))) { PLOG(ERROR) << "Failed to write .data.img.rel.ro in " << out->GetLocation(); diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h index 4e2332e3cc..43c9bc77ff 100644 --- a/dex2oat/linker/oat_writer.h +++ b/dex2oat/linker/oat_writer.h @@ -215,6 +215,10 @@ class OatWriter { return data_img_rel_ro_size_; } + size_t GetDataImgRelRoAppImageOffset() const { + return data_img_rel_ro_app_image_offset_; + } + size_t GetBssSize() const { return bss_size_; } @@ -419,6 +423,9 @@ class OatWriter { // The size of the optional .data.img.rel.ro section holding the image relocations. size_t data_img_rel_ro_size_; + // The start of app image relocations in the .data.img.rel.ro section. + size_t data_img_rel_ro_app_image_offset_; + // The start of the optional .bss section. size_t bss_start_; @@ -462,6 +469,11 @@ class OatWriter { // The value is the target offset for patching, starting at `bss_start_ + bss_methods_offset_`. SafeMap<MethodReference, size_t, MethodReferenceValueComparator> bss_method_entries_; + // Map for allocating app image Class entries in .data.img.rel.ro. Indexed by TypeReference for + // the source type in the dex file with the "type value comparator" for deduplication. The value + // is the target offset for patching, starting at `data_img_rel_ro_start_`. + SafeMap<TypeReference, size_t, TypeReferenceValueComparator> app_image_rel_ro_type_entries_; + // Map for allocating Class entries in .bss. Indexed by TypeReference for the source // type in the dex file with the "type value comparator" for deduplication. The value // is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`. diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc index 0972e5d14a..f2a6ee47f0 100644 --- a/dex2oat/linker/oat_writer_test.cc +++ b/dex2oat/linker/oat_writer_test.cc @@ -211,6 +211,7 @@ class OatTest : public CommonCompilerDriverTest { elf_writer->PrepareDynamicSection(oat_writer.GetOatHeader().GetExecutableOffset(), oat_writer.GetCodeSize(), oat_writer.GetDataImgRelRoSize(), + oat_writer.GetDataImgRelRoAppImageOffset(), oat_writer.GetBssSize(), oat_writer.GetBssMethodsOffset(), oat_writer.GetBssRootsOffset(), diff --git a/libelffile/elf/elf_builder.h b/libelffile/elf/elf_builder.h index 908ad5cb89..bb82b109bd 100644 --- a/libelffile/elf/elf_builder.h +++ b/libelffile/elf/elf_builder.h @@ -641,6 +641,7 @@ class ElfBuilder final { Elf_Word rodata_size, Elf_Word text_size, Elf_Word data_img_rel_ro_size, + Elf_Word data_img_rel_ro_app_image_offset, Elf_Word bss_size, Elf_Word bss_methods_offset, Elf_Word bss_roots_offset, @@ -682,6 +683,7 @@ class ElfBuilder final { Elf_Word oatlastword_address = rodata_.GetAddress() + rodata_size - 4; dynsym_.Add(oatlastword, &rodata_, oatlastword_address, 4, STB_GLOBAL, STT_OBJECT); } + DCHECK_LE(data_img_rel_ro_app_image_offset, data_img_rel_ro_size); if (data_img_rel_ro_size != 0u) { Elf_Word oatdataimgrelro = dynstr_.Add("oatdataimgrelro"); dynsym_.Add(oatdataimgrelro, @@ -691,14 +693,21 @@ class ElfBuilder final { STB_GLOBAL, STT_OBJECT); Elf_Word oatdataimgrelrolastword = dynstr_.Add("oatdataimgrelrolastword"); - Elf_Word oatdataimgrelrolastword_address = - data_img_rel_ro_.GetAddress() + data_img_rel_ro_size - 4; dynsym_.Add(oatdataimgrelrolastword, &data_img_rel_ro_, - oatdataimgrelrolastword_address, + data_img_rel_ro_.GetAddress() + data_img_rel_ro_size - 4, 4, STB_GLOBAL, STT_OBJECT); + if (data_img_rel_ro_app_image_offset != data_img_rel_ro_size) { + Elf_Word oatdataimgrelroappimage = dynstr_.Add("oatdataimgrelroappimage"); + dynsym_.Add(oatdataimgrelroappimage, + &data_img_rel_ro_, + data_img_rel_ro_.GetAddress() + data_img_rel_ro_app_image_offset, + data_img_rel_ro_app_image_offset, + STB_GLOBAL, + STT_OBJECT); + } } DCHECK_LE(bss_roots_offset, bss_size); if (bss_size != 0u) { diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 2c17845417..983316e9a2 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -183,6 +183,7 @@ class OatSymbolizer final { rodata_size, text_size, oat_file_->DataImgRelRoSize(), + oat_file_->DataImgRelRoAppImageOffset(), oat_file_->BssSize(), oat_file_->BssMethodsOffset(), oat_file_->BssRootsOffset(), diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h index 8910dfcbb5..c1d71e1501 100644 --- a/runtime/mirror/dex_cache.h +++ b/runtime/mirror/dex_cache.h @@ -374,7 +374,7 @@ class MANAGED DexCache final : public Object { void SetClassLoader(ObjPtr<ClassLoader> class_loader) REQUIRES_SHARED(Locks::mutator_lock_); - ObjPtr<ClassLoader> GetClassLoader() REQUIRES_SHARED(Locks::mutator_lock_); + EXPORT ObjPtr<ClassLoader> GetClassLoader() REQUIRES_SHARED(Locks::mutator_lock_); template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, ReadBarrierOption kReadBarrierOption = kWithReadBarrier, diff --git a/runtime/oat/oat.h b/runtime/oat/oat.h index 84c169a365..b850fe8dd5 100644 --- a/runtime/oat/oat.h +++ b/runtime/oat/oat.h @@ -44,8 +44,8 @@ std::ostream& operator<<(std::ostream& stream, StubType stub_type); class EXPORT PACKED(4) OatHeader { public: static constexpr std::array<uint8_t, 4> kOatMagic { { 'o', 'a', 't', '\n' } }; - // Last oat version changed reason: BSS mappings for boot image extension. - static constexpr std::array<uint8_t, 4> kOatVersion{{'2', '4', '3', '\0'}}; + // Last oat version changed reason: Implement `HLoadClass::LoadKind::kAppImageRelRo`. + static constexpr std::array<uint8_t, 4> kOatVersion{{'2', '4', '4', '\0'}}; static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline"; static constexpr const char* kDebuggableKey = "debuggable"; diff --git a/runtime/oat/oat_file.cc b/runtime/oat/oat_file.cc index 889b78f015..97db7569cf 100644 --- a/runtime/oat/oat_file.cc +++ b/runtime/oat/oat_file.cc @@ -373,6 +373,11 @@ bool OatFileBase::ComputeFields(const std::string& file_path, std::string* error } // Readjust to be non-inclusive upper bound. data_img_rel_ro_end_ += sizeof(uint32_t); + data_img_rel_ro_app_image_ = + FindDynamicSymbolAddress("oatdataimgrelroappimage", &symbol_error_msg); + if (data_img_rel_ro_app_image_ == nullptr) { + data_img_rel_ro_app_image_ = data_img_rel_ro_end_; + } } bss_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbss", &symbol_error_msg)); @@ -648,10 +653,15 @@ bool OatFileBase::Setup(int zip_fd, if (!IsAligned<sizeof(uint32_t)>(data_img_rel_ro_begin_) || !IsAligned<sizeof(uint32_t)>(data_img_rel_ro_end_) || - data_img_rel_ro_begin_ > data_img_rel_ro_end_) { - *error_msg = ErrorPrintf("unaligned or unordered databimgrelro symbol(s): begin = %p, end = %p", - data_img_rel_ro_begin_, - data_img_rel_ro_end_); + !IsAligned<sizeof(uint32_t)>(data_img_rel_ro_app_image_) || + data_img_rel_ro_begin_ > data_img_rel_ro_end_ || + data_img_rel_ro_begin_ > data_img_rel_ro_app_image_ || + data_img_rel_ro_app_image_ > data_img_rel_ro_end_) { + *error_msg = ErrorPrintf( + "unaligned or unordered databimgrelro symbol(s): begin = %p, end = %p, app_image = %p", + data_img_rel_ro_begin_, + data_img_rel_ro_end_, + data_img_rel_ro_app_image_); return false; } @@ -2015,6 +2025,7 @@ OatFile::OatFile(const std::string& location, bool is_executable) end_(nullptr), data_img_rel_ro_begin_(nullptr), data_img_rel_ro_end_(nullptr), + data_img_rel_ro_app_image_(nullptr), bss_begin_(nullptr), bss_end_(nullptr), bss_methods_(nullptr), @@ -2022,6 +2033,7 @@ OatFile::OatFile(const std::string& location, bool is_executable) is_executable_(is_executable), vdex_begin_(nullptr), vdex_end_(nullptr), + app_image_begin_(nullptr), secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) { CHECK(!location_.empty()); } @@ -2054,9 +2066,25 @@ const uint8_t* OatFile::DexEnd() const { ArrayRef<const uint32_t> OatFile::GetBootImageRelocations() const { if (data_img_rel_ro_begin_ != nullptr) { - const uint32_t* relocations = reinterpret_cast<const uint32_t*>(data_img_rel_ro_begin_); - const uint32_t* relocations_end = reinterpret_cast<const uint32_t*>(data_img_rel_ro_end_); - return ArrayRef<const uint32_t>(relocations, relocations_end - relocations); + const uint32_t* boot_image_relocations = + reinterpret_cast<const uint32_t*>(data_img_rel_ro_begin_); + const uint32_t* boot_image_relocations_end = + reinterpret_cast<const uint32_t*>(data_img_rel_ro_app_image_); + return ArrayRef<const uint32_t>( + boot_image_relocations, boot_image_relocations_end - boot_image_relocations); + } else { + return ArrayRef<const uint32_t>(); + } +} + +ArrayRef<const uint32_t> OatFile::GetAppImageRelocations() const { + if (data_img_rel_ro_begin_ != nullptr) { + const uint32_t* app_image_relocations = + reinterpret_cast<const uint32_t*>(data_img_rel_ro_app_image_); + const uint32_t* app_image_relocations_end = + reinterpret_cast<const uint32_t*>(data_img_rel_ro_end_); + return ArrayRef<const uint32_t>( + app_image_relocations, app_image_relocations_end - app_image_relocations); } else { return ArrayRef<const uint32_t>(); } @@ -2476,7 +2504,7 @@ void OatFile::InitializeRelocations() const { DCHECK(IsExecutable()); // Initialize the .data.img.rel.ro section. - if (!GetBootImageRelocations().empty()) { + if (DataImgRelRoEnd() != DataImgRelRoBegin()) { uint8_t* reloc_begin = const_cast<uint8_t*>(DataImgRelRoBegin()); CheckedCall(mprotect, "un-protect boot image relocations", @@ -2487,6 +2515,13 @@ void OatFile::InitializeRelocations() const { for (const uint32_t& relocation : GetBootImageRelocations()) { const_cast<uint32_t&>(relocation) += boot_image_begin; } + if (!GetAppImageRelocations().empty()) { + CHECK(app_image_begin_ != nullptr); + uint32_t app_image_begin = reinterpret_cast32<uint32_t>(app_image_begin_); + for (const uint32_t& relocation : GetAppImageRelocations()) { + const_cast<uint32_t&>(relocation) += app_image_begin; + } + } CheckedCall(mprotect, "protect boot image relocations", reloc_begin, diff --git a/runtime/oat/oat_file.h b/runtime/oat/oat_file.h index e17f4c43ff..579fb049f0 100644 --- a/runtime/oat/oat_file.h +++ b/runtime/oat/oat_file.h @@ -181,6 +181,12 @@ class OatFile { ClassLoaderContext* context, std::string* error_msg); + // Set the start of the app image. + // Needed for initializing app image relocations in the .data.img.rel.ro section. + void SetAppImageBegin(uint8_t* app_image_begin) const { + app_image_begin_ = app_image_begin; + } + // Return whether the `OatFile` uses a vdex-only file. bool IsBackedByVdexOnly() const; @@ -329,6 +335,10 @@ class OatFile { return DataImgRelRoEnd() - DataImgRelRoBegin(); } + size_t DataImgRelRoAppImageOffset() const { + return DataImgRelRoAppImage() - DataImgRelRoBegin(); + } + size_t BssSize() const { return BssEnd() - BssBegin(); } @@ -356,6 +366,7 @@ class OatFile { const uint8_t* DataImgRelRoBegin() const { return data_img_rel_ro_begin_; } const uint8_t* DataImgRelRoEnd() const { return data_img_rel_ro_end_; } + const uint8_t* DataImgRelRoAppImage() const { return data_img_rel_ro_app_image_; } const uint8_t* BssBegin() const { return bss_begin_; } const uint8_t* BssEnd() const { return bss_end_; } @@ -367,6 +378,7 @@ class OatFile { EXPORT const uint8_t* DexEnd() const; EXPORT ArrayRef<const uint32_t> GetBootImageRelocations() const; + EXPORT ArrayRef<const uint32_t> GetAppImageRelocations() const; EXPORT ArrayRef<ArtMethod*> GetBssMethods() const; EXPORT ArrayRef<GcRoot<mirror::Object>> GetBssGcRoots() const; @@ -429,16 +441,20 @@ class OatFile { // Pointer to the end of the .data.img.rel.ro section, if present, otherwise null. const uint8_t* data_img_rel_ro_end_; + // Pointer to the beginning of the app image relocations in the .data.img.rel.ro section, + // if present, otherwise null. + const uint8_t* data_img_rel_ro_app_image_; + // Pointer to the .bss section, if present, otherwise null. uint8_t* bss_begin_; // Pointer to the end of the .bss section, if present, otherwise null. uint8_t* bss_end_; - // Pointer to the beginning of the ArtMethod*s in .bss section, if present, otherwise null. + // Pointer to the beginning of the ArtMethod*s in the .bss section, if present, otherwise null. uint8_t* bss_methods_; - // Pointer to the beginning of the GC roots in .bss section, if present, otherwise null. + // Pointer to the beginning of the GC roots in the .bss section, if present, otherwise null. uint8_t* bss_roots_; // Was this oat_file loaded executable? @@ -450,6 +466,9 @@ class OatFile { // Pointer to the end of the .vdex section, if present, otherwise null. uint8_t* vdex_end_; + // Pointer to the beginning of the app image, if any. + mutable uint8_t* app_image_begin_; + // Owning storage for the OatDexFile objects. std::vector<const OatDexFile*> oat_dex_files_storage_; diff --git a/runtime/oat/oat_file_manager.cc b/runtime/oat/oat_file_manager.cc index 11333b0249..fea361b8ee 100644 --- a/runtime/oat/oat_file_manager.cc +++ b/runtime/oat/oat_file_manager.cc @@ -312,6 +312,7 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat( hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); // Can not load app image without class loader. if (h_loader != nullptr) { + oat_file->SetAppImageBegin(image_space->Begin()); std::string temp_error_msg; // Add image space has a race condition since other threads could be reading from the // spaces array. @@ -344,6 +345,7 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat( } } else { LOG(INFO) << "Failed to add image file: " << temp_error_msg; + oat_file->SetAppImageBegin(nullptr); dex_files.clear(); { ScopedThreadSuspension sts(self, ThreadState::kSuspended); diff --git a/test/732-checker-app-image/src-ex/Secondary.java b/test/732-checker-app-image/src-ex/Secondary.java index 52354856d6..e544e6c162 100644 --- a/test/732-checker-app-image/src-ex/Secondary.java +++ b/test/732-checker-app-image/src-ex/Secondary.java @@ -22,7 +22,7 @@ public class Secondary { } /// CHECK-START: java.lang.Class Secondary.$noinline$getSecondaryAppImageClass() builder (after) - /// CHECK: LoadClass load_kind:BssEntry in_image:true + /// CHECK: LoadClass load_kind:AppImageRelRo in_image:true public static Class<?> $noinline$getSecondaryAppImageClass() { return SecondaryAppImageClass.class; } diff --git a/test/732-checker-app-image/src/Main.java b/test/732-checker-app-image/src/Main.java index ac8d2254c9..815902940d 100644 --- a/test/732-checker-app-image/src/Main.java +++ b/test/732-checker-app-image/src/Main.java @@ -50,7 +50,7 @@ public class Main { } /// CHECK-START: java.lang.Class Main.$noinline$getAppImageClass() builder (after) - /// CHECK: LoadClass load_kind:BssEntry in_image:true + /// CHECK: LoadClass load_kind:AppImageRelRo in_image:true public static Class<?> $noinline$getAppImageClass() { return AppImageClass.class; } @@ -77,22 +77,20 @@ public class Main { } /// CHECK-START: void Main.$noinline$callAppImageClassWithClinitNop() builder (after) - /// CHECK: LoadClass load_kind:BssEntry in_image:true gen_clinit_check:false + /// CHECK: LoadClass load_kind:AppImageRelRo in_image:true gen_clinit_check:false /// CHECK: ClinitCheck /// CHECK: InvokeStaticOrDirect clinit_check:explicit /// CHECK-START: void Main.$noinline$callAppImageClassWithClinitNop() inliner (after) - /// CHECK: LoadClass load_kind:BssEntry in_image:true gen_clinit_check:false + /// CHECK: LoadClass load_kind:AppImageRelRo in_image:true gen_clinit_check:false /// CHECK: ClinitCheck /// CHECK-START: void Main.$noinline$callAppImageClassWithClinitNop() inliner (after) /// CHECK-NOT: InvokeStaticOrDirect /// CHECK-START: void Main.$noinline$callAppImageClassWithClinitNop() prepare_for_register_allocation (after) - /// CHECK: LoadClass load_kind:BssEntry in_image:true gen_clinit_check:true - - /// CHECK-START: void Main.$noinline$callAppImageClassWithClinitNop() prepare_for_register_allocation (after) - /// CHECK-NOT: ClinitCheck + /// CHECK: LoadClass load_kind:AppImageRelRo in_image:true gen_clinit_check:false + /// CHECK: ClinitCheck public static void $noinline$callAppImageClassWithClinitNop() { AppImageClassWithClinit.$inline$nop(); } |