summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/linker/linker_patch.h13
-rw-r--r--compiler/optimizing/code_generator_arm64.cc27
-rw-r--r--compiler/optimizing/code_generator_arm64.h10
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.cc20
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.h3
-rw-r--r--compiler/optimizing/code_generator_riscv64.cc23
-rw-r--r--compiler/optimizing/code_generator_riscv64.h5
-rw-r--r--compiler/optimizing/code_generator_x86.cc22
-rw-r--r--compiler/optimizing/code_generator_x86.h3
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc20
-rw-r--r--compiler/optimizing/code_generator_x86_64.h3
-rw-r--r--compiler/optimizing/nodes.h7
-rw-r--r--compiler/optimizing/sharpening.cc2
-rw-r--r--dex2oat/dex2oat.cc1
-rw-r--r--dex2oat/linker/arm64/relative_patcher_arm64.cc2
-rw-r--r--dex2oat/linker/elf_writer.h1
-rw-r--r--dex2oat/linker/elf_writer_quick.cc3
-rw-r--r--dex2oat/linker/image_test.h1
-rw-r--r--dex2oat/linker/image_writer.h9
-rw-r--r--dex2oat/linker/oat_writer.cc52
-rw-r--r--dex2oat/linker/oat_writer.h12
-rw-r--r--dex2oat/linker/oat_writer_test.cc1
-rw-r--r--libelffile/elf/elf_builder.h15
-rw-r--r--oatdump/oatdump.cc1
-rw-r--r--runtime/mirror/dex_cache.h2
-rw-r--r--runtime/oat/oat.h4
-rw-r--r--runtime/oat/oat_file.cc51
-rw-r--r--runtime/oat/oat_file.h23
-rw-r--r--runtime/oat/oat_file_manager.cc2
-rw-r--r--test/732-checker-app-image/src-ex/Secondary.java2
-rw-r--r--test/732-checker-app-image/src/Main.java12
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();
}