image_patch_delta = image_header->GetPatchDelta();
}
const OatHeader& oat_header = oat_file->GetOatHeader();
- bool ret = ((oat_header.GetImageFileLocationOatChecksum() == image_oat_checksum)
- && (oat_header.GetImagePatchDelta() == image_patch_delta)
- && (oat_header.GetImageFileLocationOatDataBegin() == image_oat_data_begin));
+ bool ret = (oat_header.GetImageFileLocationOatChecksum() == image_oat_checksum);
+
+ // If the oat file is PIC, it doesn't care if/how image was relocated. Ignore these checks.
+ if (!oat_file->IsPic()) {
+ ret = ret && (oat_header.GetImagePatchDelta() == image_patch_delta)
+ && (oat_header.GetImageFileLocationOatDataBegin() == image_oat_data_begin);
+ }
if (!ret) {
*error_msg = StringPrintf("oat file '%s' mismatch (0x%x, %d, %d) with (0x%x, %" PRIdPTR ", %d)",
oat_file->GetLocation().c_str(),
Run without dex2oat/patchoat
-dex2oat & patchoat are disabled, has oat is true, has executable oat is false.
+dex2oat & patchoat are disabled, has oat is true, has executable oat is expected.
This is a function call
Run with dexoat/patchoat
-dex2oat & patchoat are enabled, has oat is true, has executable oat is true.
+dex2oat & patchoat are enabled, has oat is true, has executable oat is expected.
This is a function call
Run default
-dex2oat & patchoat are enabled, has oat is true, has executable oat is true.
+dex2oat & patchoat are enabled, has oat is true, has executable oat is expected.
This is a function call
class NoPatchoatTest {
public:
- static bool hasExecutableOat(jclass cls) {
+ static const OatFile::OatDexFile* getOatDexFile(jclass cls) {
ScopedObjectAccess soa(Thread::Current());
mirror::Class* klass = soa.Decode<mirror::Class*>(cls);
const DexFile& dex_file = klass->GetDexFile();
+
const OatFile::OatDexFile* oat_dex_file =
Runtime::Current()->GetClassLinker()->FindOpenedOatDexFileForDexFile(dex_file);
+
+ return oat_dex_file;
+ }
+
+ static bool hasExecutableOat(jclass cls) {
+ const OatFile::OatDexFile* oat_dex_file = getOatDexFile(cls);
+
return oat_dex_file != nullptr && oat_dex_file->GetOatFile()->IsExecutable();
}
+
+ static bool isPic(jclass cls) {
+ const OatFile::OatDexFile* oat_dex_file = getOatDexFile(cls);
+
+ if (oat_dex_file == nullptr) {
+ return false;
+ }
+
+ const OatFile* oat_file = oat_dex_file->GetOatFile();
+ return oat_file->IsPic();
+ }
};
extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasExecutableOat(JNIEnv*, jclass cls) {
return NoPatchoatTest::hasExecutableOat(cls);
}
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_isPic(JNIEnv*, jclass cls) {
+ return NoPatchoatTest::isPic(cls);
+}
+
} // namespace art
public class Main {
public static void main(String[] args) {
+ boolean executable_correct = (isPic() ?
+ hasExecutableOat() == true :
+ hasExecutableOat() == isDex2OatEnabled());
+
System.out.println(
"dex2oat & patchoat are " + ((isDex2OatEnabled()) ? "enabled" : "disabled") +
- ", has oat is " + hasOat() + ", has executable oat is " + hasExecutableOat() + ".");
+ ", has oat is " + hasOat() + ", has executable oat is " + (
+ executable_correct ? "expected" : "not expected") + ".");
if (!hasOat() && isDex2OatEnabled()) {
throw new Error("Application with dex2oat enabled runs without an oat file");
private native static boolean isDex2OatEnabled();
+ private native static boolean isPic();
+
private native static boolean hasOat();
private native static boolean hasExecutableOat();