OatHeader::OatHeader(InstructionSet instruction_set, const InstructionSetFeatures* instruction_set_features,
uint32_t dex_file_count, const SafeMap<std::string, std::string>* variable_data,
uint32_t base_oat_offset)
: oat_checksum_(0u),
instruction_set_(instruction_set),
instruction_set_features_bitmap_(instruction_set_features->AsBitmap()),
dex_file_count_(dex_file_count),
oat_dex_files_offset_(0),
bcp_bss_info_offset_(0),
base_oat_offset_(base_oat_offset),
executable_offset_(0),
jni_dlsym_lookup_trampoline_offset_(0),
jni_dlsym_lookup_critical_trampoline_offset_(0),
quick_generic_jni_trampoline_offset_(0),
quick_imt_conflict_trampoline_offset_(0),
quick_resolution_trampoline_offset_(0),
quick_to_interpreter_bridge_offset_(0),
nterp_trampoline_offset_(0) { // Don't want asserts in header as they would be checked in each file that includes it. But the // fields are private, so we check inside a method.
static_assert(decltype(magic_)().size() == kOatMagic.size(), "Oat magic and magic_ have different lengths.");
static_assert(decltype(version_)().size() == kOatVersion.size(), "Oat version and version_ have different lengths.");
magic_ = kOatMagic;
version_ = kOatVersion;
CHECK_NE(instruction_set, InstructionSet::kNone);
// Flatten the map. Will also update variable_size_data_size_.
Flatten(variable_data);
}
bool OatHeader::IsValid() const { if (magic_ != kOatMagic) { returnfalse;
} if (version_ != kOatVersion) { returnfalse;
} // Only check the offset is valid after it has been set. if (executable_offset_ != 0u &&
!IsAligned<kElfSegmentAlignment>(executable_offset_ + base_oat_offset_)) { returnfalse;
} if (!IsValidInstructionSet(instruction_set_)) { returnfalse;
} returntrue;
}
std::string OatHeader::GetValidationErrorMessage() const { if (magic_ != kOatMagic) {
static_assert(kOatMagic.size() == 4, "kOatMagic has unexpected length"); return StringPrintf("Invalid oat magic, expected 0x%02x%02x%02x%02x, got 0x%02x%02x%02x%02x.",
kOatMagic[0], kOatMagic[1], kOatMagic[2], kOatMagic[3],
magic_[0], magic_[1], magic_[2], magic_[3]);
} if (version_ != kOatVersion) {
static_assert(kOatVersion.size() == 4, "kOatVersion has unexpected length"); return StringPrintf("Invalid oat version, expected 0x%02x%02x%02x%02x, got 0x%02x%02x%02x%02x.",
kOatVersion[0], kOatVersion[1], kOatVersion[2], kOatVersion[3],
version_[0], version_[1], version_[2], version_[3]);
} // Only check the offset is valid after it has been set. if (executable_offset_ != 0u &&
!IsAligned<kElfSegmentAlignment>(executable_offset_ + base_oat_offset_)) { return"Executable offset not properly aligned.";
} if (!IsValidInstructionSet(instruction_set_)) { return StringPrintf("Invalid instruction set, %d.", static_cast<int>(instruction_set_));
} return"";
}
// Do not move this into the header. The method must be compiled in the runtime library, // so that we can check that the compile-time oat version matches the version in the caller. void OatHeader::CheckOatVersion(std::array<uint8_t, 4> version) {
constexpr std::array<uint8_t, 4> expected = kOatVersion; // Runtime oat version. if (version != kOatVersion) {
LOG(FATAL) << StringPrintf("Invalid oat version, expected 0x%02x%02x%02x%02x, " "got 0x%02x%02x%02x%02x.",
expected[0], expected[1], expected[2], expected[3],
version[0], version[1], version[2], version[3]);
}
}
const uint8_t* OatHeader::GetOatAddress(StubType type) const {
DCHECK_LE(type, StubType::kLast); switch (type) { // TODO: We could maybe clean this up if we stored them in an array in the oat header. case StubType::kQuickGenericJNITrampoline: returnstatic_cast<const uint8_t*>(GetQuickGenericJniTrampoline()); case StubType::kJNIDlsymLookupTrampoline: returnstatic_cast<const uint8_t*>(GetJniDlsymLookupTrampoline()); case StubType::kJNIDlsymLookupCriticalTrampoline: returnstatic_cast<const uint8_t*>(GetJniDlsymLookupCriticalTrampoline()); case StubType::kQuickIMTConflictTrampoline: returnstatic_cast<const uint8_t*>(GetQuickImtConflictTrampoline()); case StubType::kQuickResolutionTrampoline: returnstatic_cast<const uint8_t*>(GetQuickResolutionTrampoline()); case StubType::kQuickToInterpreterBridge: returnstatic_cast<const uint8_t*>(GetQuickToInterpreterBridge()); case StubType::kNterpTrampoline: returnstatic_cast<const uint8_t*>(GetNterpTrampoline());
}
}
} // namespace art
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.2 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.