[C++] 纯文本查看 复制代码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;
}
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(),
Size(),
sizeof(OatHeader),
key_value_store_size);
return false;
}
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.//oat指针跳到OatDexFile去
DCHECK_GE(static_cast(pointer_size), alignof(GcRoot<:object>));
if (!IsAligned(bss_begin_) ||
!IsAlignedParam(bss_methods_, static_cast(pointer_size)) ||
!IsAlignedParam(bss_roots_, static_cast(pointer_size)) ||
!IsAligned)>(bss_end_)) {
*error_msg = StringPrintf("In oat file '%s' found unaligned bss symbol(s): "
"begin = %p, methods_ = %p, roots = %p, end = %p",
GetLocation().c_str(),
bss_begin_,
bss_methods_,
bss_roots_,
bss_end_);
return false;
}
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_begin_,
bss_methods_,
bss_roots_,
bss_end_);
return false;
}
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_ == 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();//获得dex_file_count
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))) //循环通过ReadOatDexFileData函数读取dex_file_location_size并调整oat指针
*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(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(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))) {//通过ReadOatDexFileData函数读取dex_file_checksum并调整oat指针
*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))) {//通过ReadOatDexFileData函数读取dex_file_offset并调整oat指针
*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 > DexSize())) {
*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,
DexSize());
return false;
}
if (UNLIKELY(DexSize() - 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,
DexSize(),
sizeof(DexFile::Header));
return false;
}
const uint8_t* dex_file_pointer = DexBegin() + 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(dex_file_pointer);
if (DexSize() - 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_,
DexSize());
return false;
}
uint32_t class_offsets_offset;
if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &class_offsets_offset))) {//通过ReadOatDexFileData函数读取class_offsets_offset并调整oat指针
*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(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(Begin() + class_offsets_offset);
uint32_t lookup_table_offset;
if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &lookup_table_offset))) {//通过ReadOatDexFileData函数读取lookup_table_offset并调整oat指针,lookup_table用于加速类的查找
*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;
}
uint32_t dex_layout_sections_offset;
if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_layout_sections_offset))) {//通过ReadOatDexFileData函数读取dex_layout_sections_offset并调整oat指针
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
"after dex layout sections offset",
GetLocation().c_str(),
i,
dex_file_location.c_str());
return false;
}
const DexLayoutSections* const dex_layout_sections = dex_layout_sections_offset != 0
? reinterpret_cast(Begin() + dex_layout_sections_offset)
: nullptr;
uint32_t method_bss_mapping_offset;
if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &method_bss_mapping_offset))) {//通过ReadOatDexFileData函数读取method_bss_mapping_offset并调整oat指针
*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(method_bss_mapping_offset) &&
Size() - method_bss_mapping_offset >= MethodBssMapping::ComputeSize(0);
const MethodBssMapping* method_bss_mapping = readable_method_bss_mapping_size
? reinterpret_cast(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(pointer_size));
CHECK_LT(entry.bss_offset, BssSize());
CHECK_LE(POPCOUNT(entry.index_mask) * static_cast(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(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
// DexFile header. For CallSites, we need to read the info from the MapList.
//对于CallSites,必须从MapList中读取,他不存储在header中
const DexFile::MapItem* call_sites_item = nullptr;
if (!FindDexFileMapItem(DexBegin(), //通过FindDexFileMapItem读取call_sites_item并解析
DexEnd(),
DexFile::MapItemType::kDexTypeCallSiteIdItem,
&call_sites_item)) {
*error_msg = StringPrintf("In oat file '%s' could not read data from truncated DexFile map",
GetLocation().c_str());
return false;
}
size_t num_call_sites = call_sites_item == nullptr ? 0 : call_sites_item->size_;
DexCacheArraysLayout layout(pointer_size, *header, num_call_sites);
if (layout.Size() != 0u) {
if (static_cast(dex_cache_arrays_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(dex_cache_arrays_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, //根据上面ReadOatDexFileData和FindDexFileMapItem获得的信息构建oat_dex_file
dex_file_location,
canonical_location,
dex_file_checksum,
dex_file_pointer,
lookup_table_data,
method_bss_mapping,
class_offsets_pointer,
current_dex_cache_arrays,
dex_layout_sections);
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 != dex_cache_arrays_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 optionally some GC roots.
*error_msg = StringPrintf("In oat file '%s' found unexpected bss size bigger by %zu bytes.",
GetLocation().c_str(),
static_cast(bss_end_ - dex_cache_arrays));
return false;
}
return true;
}