ART: Fix crash accessing .bss for non-executable oat file.
There are situations where we're running and JIT-compiling
bytecode from a dex file tied to a non-executable oat file
(i.e. its AOT-compiled code cannot be executed) and the
JIT-compiled code can try to store the resolved class or
string in its .bss section which has not been mmapped.
Check whether the oat file is executable before doing the
.bss store.
Note that clearing the pointers to index bss mappings when
loading the oat file as non-executable would also solve the
problem. However, that would prevent oatdump from listing
.bss entries.
Test: No regression test provided, oat files are loaded
as non-executable only in some odd situations that
are very difficult to replicate in a test.
Bug: 69928566
Change-Id: Ib91d22f6510dc0d7cc9abe8247f2743706aaa45e
diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
index f756312..238ada9 100644
--- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
@@ -41,6 +41,12 @@
static_assert(sizeof(GcRoot<mirror::String>) == sizeof(GcRoot<mirror::Object>), "Size check.");
DCHECK_NE(bss_offset, IndexBssMappingLookup::npos);
DCHECK_ALIGNED(bss_offset, sizeof(GcRoot<mirror::Object>));
+ if (UNLIKELY(!oat_file->IsExecutable())) {
+ // There are situations where we execute bytecode tied to an oat file opened
+ // as non-executable (i.e. the AOT-compiled code cannot be executed) and we
+ // can JIT that bytecode and get here without the .bss being mmapped.
+ return;
+ }
GcRoot<mirror::Object>* slot = reinterpret_cast<GcRoot<mirror::Object>*>(
const_cast<uint8_t*>(oat_file->BssBegin() + bss_offset));
DCHECK_GE(slot, oat_file->GetBssGcRoots().data());