Use ArtMethod* .bss entries for HInvokeStaticOrDirect.
Test: m test-art-host-gtest
Test: testrunner.py --host
Test: testrunner.py --target
Test: Nexus 6P boots.
Test: Build aosp_mips64-userdebug.
Bug: 30627598
Change-Id: I0e54fdd2e91e983d475b7a04d40815ba89ae3d4f
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index a816522..888de45 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -246,6 +246,9 @@
}
// Readjust to be non-inclusive upper bound.
bss_end_ += sizeof(uint32_t);
+ // Find bss methods if present.
+ bss_methods_ =
+ const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssmethods", &symbol_error_msg));
// Find bss roots if present.
bss_roots_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssroots", &symbol_error_msg));
}
@@ -311,51 +314,63 @@
cause.c_str());
return false;
}
- const uint8_t* oat = Begin();
- oat += sizeof(OatHeader);
- if (oat > End()) {
- *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader", GetLocation().c_str());
- return false;
- }
-
- oat += GetOatHeader().GetKeyValueStoreSize();
- if (oat > End()) {
- *error_msg = StringPrintf("In oat file '%s' found truncated variable-size data: "
- "%p + %zu + %u <= %p",
+ PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
+ size_t key_value_store_size =
+ (Size() >= sizeof(OatHeader)) ? GetOatHeader().GetKeyValueStoreSize() : 0u;
+ if (Size() < sizeof(OatHeader) + key_value_store_size) {
+ *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader, "
+ "size = %zu < %zu + %zu",
GetLocation().c_str(),
- Begin(),
+ Size(),
sizeof(OatHeader),
- GetOatHeader().GetKeyValueStoreSize(),
- End());
+ key_value_store_size);
return false;
}
- if (!IsAligned<alignof(GcRoot<mirror::Object>)>(bss_begin_) ||
- !IsAligned<alignof(GcRoot<mirror::Object>)>(bss_roots_) ||
+ size_t oat_dex_files_offset = GetOatHeader().GetOatDexFilesOffset();
+ if (oat_dex_files_offset < GetOatHeader().GetHeaderSize() || oat_dex_files_offset > Size()) {
+ *error_msg = StringPrintf("In oat file '%s' found invalid oat dex files offset: "
+ "%zu is not in [%zu, %zu]",
+ GetLocation().c_str(),
+ oat_dex_files_offset,
+ GetOatHeader().GetHeaderSize(),
+ Size());
+ return false;
+ }
+ const uint8_t* oat = Begin() + oat_dex_files_offset; // Jump to the OatDexFile records.
+
+ DCHECK_GE(static_cast<size_t>(pointer_size), alignof(GcRoot<mirror::Object>));
+ if (!IsAligned<kPageSize>(bss_begin_) ||
+ !IsAlignedParam(bss_methods_, static_cast<size_t>(pointer_size)) ||
+ !IsAlignedParam(bss_roots_, static_cast<size_t>(pointer_size)) ||
!IsAligned<alignof(GcRoot<mirror::Object>)>(bss_end_)) {
*error_msg = StringPrintf("In oat file '%s' found unaligned bss symbol(s): "
- "begin = %p, roots = %p, end = %p",
+ "begin = %p, methods_ = %p, roots = %p, end = %p",
GetLocation().c_str(),
bss_begin_,
+ bss_methods_,
bss_roots_,
bss_end_);
return false;
}
- if (bss_roots_ != nullptr && (bss_roots_ < bss_begin_ || bss_roots_ > bss_end_)) {
- *error_msg = StringPrintf("In oat file '%s' found bss roots outside .bss: "
- "%p is outside range [%p, %p]",
+ if ((bss_methods_ != nullptr && (bss_methods_ < bss_begin_ || bss_methods_ > bss_end_)) ||
+ (bss_roots_ != nullptr && (bss_roots_ < bss_begin_ || bss_roots_ > bss_end_)) ||
+ (bss_methods_ != nullptr && bss_roots_ != nullptr && bss_methods_ > bss_roots_)) {
+ *error_msg = StringPrintf("In oat file '%s' found bss symbol(s) outside .bss or unordered: "
+ "begin = %p, methods_ = %p, roots = %p, end = %p",
GetLocation().c_str(),
- bss_roots_,
bss_begin_,
+ bss_methods_,
+ bss_roots_,
bss_end_);
return false;
}
- PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
- uint8_t* dex_cache_arrays = (bss_begin_ == bss_roots_) ? nullptr : bss_begin_;
+ uint8_t* after_arrays = (bss_methods_ != nullptr) ? bss_methods_ : bss_roots_; // May be null.
+ uint8_t* dex_cache_arrays = (bss_begin_ == after_arrays) ? nullptr : bss_begin_;
uint8_t* dex_cache_arrays_end =
- (bss_begin_ == bss_roots_) ? nullptr : (bss_roots_ != nullptr) ? bss_roots_ : bss_end_;
+ (bss_begin_ == after_arrays) ? nullptr : (after_arrays != nullptr) ? after_arrays : bss_end_;
DCHECK_EQ(dex_cache_arrays != nullptr, dex_cache_arrays_end != nullptr);
uint32_t dex_file_count = GetOatHeader().GetDexFileCount();
oat_dex_files_storage_.reserve(dex_file_count);
@@ -529,6 +544,55 @@
return false;
}
+ uint32_t method_bss_mapping_offset;
+ if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &method_bss_mapping_offset))) {
+ *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
+ "after method bss mapping offset",
+ GetLocation().c_str(),
+ i,
+ dex_file_location.c_str());
+ return false;
+ }
+ const bool readable_method_bss_mapping_size =
+ method_bss_mapping_offset != 0u &&
+ method_bss_mapping_offset <= Size() &&
+ IsAligned<alignof(MethodBssMapping)>(method_bss_mapping_offset) &&
+ Size() - method_bss_mapping_offset >= MethodBssMapping::ComputeSize(0);
+ const MethodBssMapping* method_bss_mapping = readable_method_bss_mapping_size
+ ? reinterpret_cast<const MethodBssMapping*>(Begin() + method_bss_mapping_offset)
+ : nullptr;
+ if (method_bss_mapping_offset != 0u &&
+ (UNLIKELY(method_bss_mapping == nullptr) ||
+ UNLIKELY(method_bss_mapping->size() == 0u) ||
+ UNLIKELY(Size() - method_bss_mapping_offset <
+ MethodBssMapping::ComputeSize(method_bss_mapping->size())))) {
+ *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned or "
+ " truncated method bss mapping, offset %u of %zu, length %zu",
+ GetLocation().c_str(),
+ i,
+ dex_file_location.c_str(),
+ method_bss_mapping_offset,
+ Size(),
+ method_bss_mapping != nullptr ? method_bss_mapping->size() : 0u);
+ return false;
+ }
+ if (kIsDebugBuild && method_bss_mapping != nullptr) {
+ const MethodBssMappingEntry* prev_entry = nullptr;
+ for (const MethodBssMappingEntry& entry : *method_bss_mapping) {
+ CHECK_ALIGNED_PARAM(entry.bss_offset, static_cast<size_t>(pointer_size));
+ CHECK_LT(entry.bss_offset, BssSize());
+ CHECK_LE(POPCOUNT(entry.index_mask) * static_cast<size_t>(pointer_size), entry.bss_offset);
+ size_t index_mask_span = (entry.index_mask != 0u) ? 16u - CTZ(entry.index_mask) : 0u;
+ CHECK_LE(index_mask_span, entry.method_index);
+ if (prev_entry != nullptr) {
+ CHECK_LT(prev_entry->method_index, entry.method_index - index_mask_span);
+ }
+ prev_entry = &entry;
+ }
+ CHECK_LT(prev_entry->method_index,
+ reinterpret_cast<const DexFile::Header*>(dex_file_pointer)->method_ids_size_);
+ }
+
uint8_t* current_dex_cache_arrays = nullptr;
if (dex_cache_arrays != nullptr) {
// All DexCache types except for CallSite have their instance counts in the
@@ -569,6 +633,7 @@
dex_file_checksum,
dex_file_pointer,
lookup_table_data,
+ method_bss_mapping,
class_offsets_pointer,
current_dex_cache_arrays);
oat_dex_files_storage_.push_back(oat_dex_file);
@@ -1158,6 +1223,7 @@
end_(nullptr),
bss_begin_(nullptr),
bss_end_(nullptr),
+ bss_methods_(nullptr),
bss_roots_(nullptr),
is_executable_(is_executable),
secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) {
@@ -1198,6 +1264,17 @@
return kIsVdexEnabled ? vdex_->End() : End();
}
+ArrayRef<ArtMethod*> OatFile::GetBssMethods() const {
+ if (bss_methods_ != nullptr) {
+ ArtMethod** methods = reinterpret_cast<ArtMethod**>(bss_methods_);
+ ArtMethod** methods_end =
+ reinterpret_cast<ArtMethod**>(bss_roots_ != nullptr ? bss_roots_ : bss_end_);
+ return ArrayRef<ArtMethod*>(methods, methods_end - methods);
+ } else {
+ return ArrayRef<ArtMethod*>();
+ }
+}
+
ArrayRef<GcRoot<mirror::Object>> OatFile::GetBssGcRoots() const {
if (bss_roots_ != nullptr) {
auto* roots = reinterpret_cast<GcRoot<mirror::Object>*>(bss_roots_);
@@ -1283,6 +1360,7 @@
uint32_t dex_file_location_checksum,
const uint8_t* dex_file_pointer,
const uint8_t* lookup_table_data,
+ const MethodBssMapping* method_bss_mapping_data,
const uint32_t* oat_class_offsets_pointer,
uint8_t* dex_cache_arrays)
: oat_file_(oat_file),
@@ -1291,6 +1369,7 @@
dex_file_location_checksum_(dex_file_location_checksum),
dex_file_pointer_(dex_file_pointer),
lookup_table_data_(lookup_table_data),
+ method_bss_mapping_(method_bss_mapping_data),
oat_class_offsets_pointer_(oat_class_offsets_pointer),
dex_cache_arrays_(dex_cache_arrays) {
// Initialize TypeLookupTable.