diff options
-rw-r--r-- | runtime/oat.cc | 34 | ||||
-rw-r--r-- | runtime/oat.h | 5 | ||||
-rw-r--r-- | runtime/oat_file.cc | 4 |
3 files changed, 38 insertions, 5 deletions
diff --git a/runtime/oat.cc b/runtime/oat.cc index 9307598..c223e2e 100644 --- a/runtime/oat.cc +++ b/runtime/oat.cc @@ -20,12 +20,13 @@ #include <zlib.h> #include "arch/instruction_set_features.h" +#include "base/stringprintf.h" #include "utils.h" namespace art { -const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' }; -const uint8_t OatHeader::kOatVersion[] = { '0', '5', '2', '\0' }; +constexpr uint8_t OatHeader::kOatMagic[4]; +constexpr uint8_t OatHeader::kOatVersion[4]; static size_t ComputeOatHeaderSize(const SafeMap<std::string, std::string>* variable_data) { size_t estimate = 0U; @@ -67,6 +68,13 @@ OatHeader::OatHeader(InstructionSet instruction_set, uint32_t image_file_location_oat_checksum, uint32_t image_file_location_oat_data_begin, const SafeMap<std::string, std::string>* variable_data) { + // 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(sizeof(magic_) == sizeof(kOatMagic), + "Oat magic and magic_ have different lengths."); + static_assert(sizeof(version_) == sizeof(kOatVersion), + "Oat version and version_ have different lengths."); + memcpy(magic_, kOatMagic, sizeof(kOatMagic)); memcpy(version_, kOatVersion, sizeof(kOatVersion)); executable_offset_ = 0; @@ -127,6 +135,28 @@ bool OatHeader::IsValid() const { return true; } +std::string OatHeader::GetValidationErrorMessage() const { + if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) { + static_assert(sizeof(kOatMagic) == 4, "kOatMagic has unexpected length"); + return StringPrintf("Invalid oat magic, expected 0x%x%x%x%x, got 0x%x%x%x%x.", + kOatMagic[0], kOatMagic[1], kOatMagic[2], kOatMagic[3], + magic_[0], magic_[1], magic_[2], magic_[3]); + } + if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) { + static_assert(sizeof(kOatVersion) == 4, "kOatVersion has unexpected length"); + return StringPrintf("Invalid oat version, expected 0x%x%x%x%x, got 0x%x%x%x%x.", + kOatVersion[0], kOatVersion[1], kOatVersion[2], kOatVersion[3], + version_[0], version_[1], version_[2], version_[3]); + } + if (!IsAligned<kPageSize>(executable_offset_)) { + return "Executable offset not page-aligned."; + } + if (!IsAligned<kPageSize>(image_patch_delta_)) { + return "Image patch delta not page-aligned."; + } + return ""; +} + const char* OatHeader::GetMagic() const { CHECK(IsValid()); return reinterpret_cast<const char*>(magic_); diff --git a/runtime/oat.h b/runtime/oat.h index 6098fbd..f218482 100644 --- a/runtime/oat.h +++ b/runtime/oat.h @@ -31,8 +31,8 @@ class InstructionSetFeatures; class PACKED(4) OatHeader { public: - static const uint8_t kOatMagic[4]; - static const uint8_t kOatVersion[4]; + static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' }; + static constexpr uint8_t kOatVersion[] = { '0', '4', '5', '\0' }; static constexpr const char* kImageLocationKey = "image-location"; static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline"; @@ -47,6 +47,7 @@ class PACKED(4) OatHeader { const SafeMap<std::string, std::string>* variable_data); bool IsValid() const; + std::string GetValidationErrorMessage() const; const char* GetMagic() const; uint32_t GetChecksum() const; void UpdateChecksum(const void* data, size_t length); diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index aa85ff0..1c6cc8b 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -227,7 +227,9 @@ bool OatFile::ElfFileOpen(File* file, uint8_t* requested_base, uint8_t* oat_file bool OatFile::Setup(std::string* error_msg) { if (!GetOatHeader().IsValid()) { - *error_msg = StringPrintf("Invalid oat magic for '%s'", GetLocation().c_str()); + 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(); |