std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex_filename.c_str())); if (vdex_file == nullptr) {
*error_msg = "Could not open file for reading"; return nullptr;
}
int64_t vdex_length = vdex_file->GetLength(); if (vdex_length == -1) {
*error_msg = "Could not read the length of file " + vdex_filename; return nullptr;
}
std::unique_ptr<VdexFile> VdexFile::OpenFromDm(const ZipArchive& archive, const std::string& filename,
std::string* error_msg) {
std::unique_ptr<ZipEntry> zip_entry(archive.Find(VdexFile::kVdexNameInDmFile, error_msg)); if (zip_entry == nullptr) {
*error_msg = ART_FORMAT("No {} file in DexMetadata archive. Not doing fast verification: {}",
VdexFile::kVdexNameInDmFile,
*error_msg); return nullptr;
}
MemMap input_file = zip_entry->MapDirectlyOrExtract(
filename.c_str(), VdexFile::kVdexNameInDmFile, error_msg, alignof(VdexFile)); if (!input_file.IsValid()) {
*error_msg = "Could not open vdex file in DexMetadata archive: " + *error_msg; return nullptr;
}
std::unique_ptr<VdexFile> vdex_file = std::make_unique<VdexFile>(std::move(input_file)); if (!vdex_file->IsValid()) {
*error_msg = "The dex metadata .vdex is not valid. Ignoring it."; return nullptr;
} if (vdex_file->HasDexSection()) {
*error_msg = "The dex metadata is not allowed to contain dex files";
android_errorWriteLog(0x534e4554, "178055795"); // Report to SafetyNet. return nullptr;
} return vdex_file;
}
const uint8_t* VdexFile::GetNextDexFileData(const uint8_t* cursor, uint32_t dex_file_index) const {
DCHECK(cursor == nullptr || (cursor > Begin() && cursor <= End())); if (cursor == nullptr) { // Beginning of the iteration, return the first dex file if there is one. return HasDexSection() ? DexBegin() : nullptr;
} elseif (dex_file_index >= GetNumberOfDexFiles()) { return nullptr;
} else { // Fetch the next dex file. Return null if there is none. const uint8_t* data = cursor + reinterpret_cast<const DexFile::Header*>(cursor)->file_size_; // Dex files are required to be 4 byte aligned. the OatWriter makes sure they are, see // OatWriter::SeekToDexFiles. return AlignUp(data, 4);
}
}
const uint8_t* VdexFile::GetNextTypeLookupTableData(const uint8_t* cursor,
uint32_t dex_file_index) const { if (cursor == nullptr) { // Beginning of the iteration, return the first dex file if there is one. return HasTypeLookupTableSection() ? TypeLookupTableDataBegin() : nullptr;
} elseif (dex_file_index >= GetNumberOfDexFiles()) { return nullptr;
} else { const uint8_t* data = cursor + sizeof(uint32_t) + reinterpret_cast<const uint32_t*>(cursor)[0]; // TypeLookupTables are required to be 4 byte aligned. the OatWriter makes sure they are. // We don't check this here to be defensive against corrupted vdex files. // Callers should check the returned value matches their expectations. return data;
}
}
// Returns an array of offsets where the assignability checks for each class // definition are stored. staticconst uint32_t* GetDexFileClassDefs(const uint8_t* verifier_deps, uint32_t index) {
uint32_t dex_file_offset = reinterpret_cast<const uint32_t*>(verifier_deps)[index]; returnreinterpret_cast<const uint32_t*>(verifier_deps + dex_file_offset);
}
// Returns an array of offsets where extra strings are stored. staticconst uint32_t* GetExtraStringsOffsets(const DexFile& dex_file, const uint8_t* verifier_deps, const uint32_t* dex_file_class_defs, /*out*/ uint32_t* number_of_extra_strings) { // The information for strings is right after dex_file_class_defs, 4-byte // aligned
uint32_t end_of_assignability_types = dex_file_class_defs[dex_file.NumClassDefs()]; const uint8_t* strings_data_start =
AlignUp(verifier_deps + end_of_assignability_types, sizeof(uint32_t)); // First entry is the number of extra strings for this dex file.
*number_of_extra_strings = *reinterpret_cast<const uint32_t*>(strings_data_start); // Then an array of offsets in `verifier_deps` for the extra strings. returnreinterpret_cast<const uint32_t*>(strings_data_start + sizeof(uint32_t));
}
// Fetch type checks offsets.
uint32_t class_def_offset = dex_file_class_defs[class_def_index]; if (class_def_offset == verifier::VerifierDeps::kNotVerifiedMarker) { // Return a status that needs re-verification. return ClassStatus::kResolved;
} // End offset for this class's type checks. We know there is one and the loop // will terminate.
uint32_t end_offset = verifier::VerifierDeps::kNotVerifiedMarker; for (uint32_t i = class_def_index + 1; i < dex_file.NumClassDefs() + 1; ++i) {
end_offset = dex_file_class_defs[i]; if (end_offset != verifier::VerifierDeps::kNotVerifiedMarker) { break;
}
}
DCHECK_NE(end_offset, verifier::VerifierDeps::kNotVerifiedMarker);
uint32_t number_of_extra_strings = 0; // Offset where extra strings are stored. const uint32_t* extra_strings_offsets = GetExtraStringsOffsets(dex_file,
verifier_deps,
dex_file_class_defs,
&number_of_extra_strings);
// Loop over and perform each assignability check.
StackHandleScope<3> hs(self);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(cls->GetClassLoader()));
MutableHandle<mirror::Class> source(hs.NewHandle<mirror::Class>(nullptr));
MutableHandle<mirror::Class> destination(hs.NewHandle<mirror::Class>(nullptr));
const uint8_t* cursor = verifier_deps + class_def_offset; const uint8_t* end = verifier_deps + end_offset; while (cursor < end) {
uint32_t destination_index;
uint32_t source_index; if (UNLIKELY(!DecodeUnsignedLeb128Checked(&cursor, end, &destination_index) ||
!DecodeUnsignedLeb128Checked(&cursor, end, &source_index))) { // Error parsing the data, just return that we are not verified. return ClassStatus::kResolved;
}
size_t destination_desc_length; constchar* destination_desc = GetStringFromIndex(dex_file,
dex::StringIndex(destination_index),
number_of_extra_strings,
extra_strings_offsets,
verifier_deps,
&destination_desc_length);
destination.Assign(FindClassAndClearException(
class_linker, self, destination_desc, destination_desc_length, class_loader));
if (destination == nullptr || source == nullptr) {
cls->SetHasTypeChecksFailure(); // The interpreter / compiler can handle a missing class. continue;
}
DCHECK(destination->IsResolved() && source->IsResolved()); if (!destination->IsAssignableFrom(source.Get())) {
VLOG(verifier) << "Vdex checking failed for " << cls->PrettyClass()
<< ": expected " << destination->PrettyClass()
<< " to be assignable from " << source->PrettyClass(); // An implicit assignability check is failing in the code, return that the // class is not verified. return ClassStatus::kResolved;
}
}
return ClassStatus::kVerifiedNeedsAccessChecks;
}
} // namespace art
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.21 Sekunden
(vorverarbeitet am 2026-06-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.