in runtime/oat_file.cc [236:487]
bool OatFileBase::Setup(const char* abs_dex_location, std::string* error_msg) {
if (!GetOatHeader().IsValid()) {
std::string cause = GetOatHeader().GetValidationErrorMessage();
*error_msg = StringPrintf("Invalid oat header for '%s': %s",
GetLocation().c_str(),
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",
GetLocation().c_str(),
Begin(),
sizeof(OatHeader),
GetOatHeader().GetKeyValueStoreSize(),
End());
return false;
}
size_t pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
uint8_t* dex_cache_arrays = bss_begin_;
uint32_t dex_file_count = GetOatHeader().GetDexFileCount();
oat_dex_files_storage_.reserve(dex_file_count);
for (size_t i = 0; i < dex_file_count; i++) {
uint32_t dex_file_location_size;
if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_location_size))) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu truncated after dex file "
"location size",
GetLocation().c_str(),
i);
return false;
}
if (UNLIKELY(dex_file_location_size == 0U)) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with empty location name",
GetLocation().c_str(),
i);
return false;
}
if (UNLIKELY(static_cast<size_t>(End() - oat) < dex_file_location_size)) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with truncated dex file "
"location",
GetLocation().c_str(),
i);
return false;
}
const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
oat += dex_file_location_size;
std::string dex_file_location = ResolveRelativeEncodedDexLocation(
abs_dex_location,
std::string(dex_file_location_data, dex_file_location_size));
uint32_t dex_file_checksum;
if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_checksum))) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated after "
"dex file checksum",
GetLocation().c_str(),
i,
dex_file_location.c_str());
return false;
}
uint32_t dex_file_offset;
if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_offset))) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
"after dex file offsets",
GetLocation().c_str(),
i,
dex_file_location.c_str());
return false;
}
if (UNLIKELY(dex_file_offset == 0U)) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with zero dex "
"file offset",
GetLocation().c_str(),
i,
dex_file_location.c_str());
return false;
}
if (UNLIKELY(dex_file_offset > Size())) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
"offset %u > %zu",
GetLocation().c_str(),
i,
dex_file_location.c_str(),
dex_file_offset,
Size());
return false;
}
if (UNLIKELY(Size() - dex_file_offset < sizeof(DexFile::Header))) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
"offset %u of %zu but the size of dex file header is %zu",
GetLocation().c_str(),
i,
dex_file_location.c_str(),
dex_file_offset,
Size(),
sizeof(DexFile::Header));
return false;
}
const uint8_t* dex_file_pointer = Begin() + dex_file_offset;
if (UNLIKELY(!DexFile::IsMagicValid(dex_file_pointer))) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
"dex file magic '%s'",
GetLocation().c_str(),
i,
dex_file_location.c_str(),
dex_file_pointer);
return false;
}
if (UNLIKELY(!DexFile::IsVersionValid(dex_file_pointer))) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
"dex file version '%s'",
GetLocation().c_str(),
i,
dex_file_location.c_str(),
dex_file_pointer);
return false;
}
const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
if (Size() - dex_file_offset < header->file_size_) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
"offset %u and size %u truncated at %zu",
GetLocation().c_str(),
i,
dex_file_location.c_str(),
dex_file_offset,
header->file_size_,
Size());
return false;
}
uint32_t class_offsets_offset;
if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &class_offsets_offset))) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
"after class offsets offset",
GetLocation().c_str(),
i,
dex_file_location.c_str());
return false;
}
if (UNLIKELY(class_offsets_offset > Size()) ||
UNLIKELY((Size() - class_offsets_offset) / sizeof(uint32_t) < header->class_defs_size_)) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
"class offsets, offset %u of %zu, class defs %u",
GetLocation().c_str(),
i,
dex_file_location.c_str(),
class_offsets_offset,
Size(),
header->class_defs_size_);
return false;
}
if (UNLIKELY(!IsAligned<alignof(uint32_t)>(class_offsets_offset))) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned "
"class offsets, offset %u",
GetLocation().c_str(),
i,
dex_file_location.c_str(),
class_offsets_offset);
return false;
}
const uint32_t* class_offsets_pointer =
reinterpret_cast<const uint32_t*>(Begin() + class_offsets_offset);
uint32_t lookup_table_offset;
if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &lookup_table_offset))) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
"after lookup table offset",
GetLocation().c_str(),
i,
dex_file_location.c_str());
return false;
}
const uint8_t* lookup_table_data = lookup_table_offset != 0u
? Begin() + lookup_table_offset
: nullptr;
if (lookup_table_offset != 0u &&
(UNLIKELY(lookup_table_offset > Size()) ||
UNLIKELY(Size() - lookup_table_offset <
TypeLookupTable::RawDataLength(header->class_defs_size_)))) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
"type lookup table, offset %u of %zu, class defs %u",
GetLocation().c_str(),
i,
dex_file_location.c_str(),
lookup_table_offset,
Size(),
header->class_defs_size_);
return false;
}
uint8_t* current_dex_cache_arrays = nullptr;
if (dex_cache_arrays != nullptr) {
DexCacheArraysLayout layout(pointer_size, *header);
if (layout.Size() != 0u) {
if (static_cast<size_t>(bss_end_ - dex_cache_arrays) < layout.Size()) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with "
"truncated dex cache arrays, %zu < %zu.",
GetLocation().c_str(),
i,
dex_file_location.c_str(),
static_cast<size_t>(bss_end_ - dex_cache_arrays),
layout.Size());
return false;
}
current_dex_cache_arrays = dex_cache_arrays;
dex_cache_arrays += layout.Size();
}
}
std::string canonical_location = DexFile::GetDexCanonicalLocation(dex_file_location.c_str());
// Create the OatDexFile and add it to the owning container.
OatDexFile* oat_dex_file = new OatDexFile(this,
dex_file_location,
canonical_location,
dex_file_checksum,
dex_file_pointer,
lookup_table_data,
class_offsets_pointer,
current_dex_cache_arrays);
oat_dex_files_storage_.push_back(oat_dex_file);
// Add the location and canonical location (if different) to the oat_dex_files_ table.
StringPiece key(oat_dex_file->GetDexFileLocation());
oat_dex_files_.Put(key, oat_dex_file);
if (canonical_location != dex_file_location) {
StringPiece canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
oat_dex_files_.Put(canonical_key, oat_dex_file);
}
}
if (dex_cache_arrays != bss_end_) {
// We expect the bss section to be either empty (dex_cache_arrays and bss_end_
// both null) or contain just the dex cache arrays and nothing else.
*error_msg = StringPrintf("In oat file '%s' found unexpected bss size bigger by %zu bytes.",
GetLocation().c_str(),
static_cast<size_t>(bss_end_ - dex_cache_arrays));
return false;
}
return true;
}