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<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, 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<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))) {//通过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<const DexFile::Header*>(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<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))) {//通过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<const DexLayoutSections*>(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<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 // 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<size_t>(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<size_t>(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<size_t>(bss_end_ - dex_cache_arrays)); return false; } return true; }
根据以上几步,最终通过oat_file获得了oat_dex_file.
由于菜鸟有些地方也没搞太明白,中间免不了有一些错误,有些语句也叙述的不够恰当,毕竟外行而且语文不咋地,但大致流程应该没问题,希望各位大佬指出我的问题,我好早日改正。