Check the machine type of an ELF file when loading.

This ensures that we reject wrong target ELF files,
and should result in a recompile for the right
target.

Change-Id: I898dddc4f2bb9b1607a7436083d0ba7619b6007b
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index f665f5c..c6e448e 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -743,19 +743,7 @@
   InstructionSetFeatures instruction_set_features =
       ParseFeatureList(Runtime::GetDefaultInstructionSetFeatures());
 
-#if defined(__arm__)
-  InstructionSet instruction_set = kThumb2;
-#elif defined(__aarch64__)
-  InstructionSet instruction_set = kArm64;
-#elif defined(__i386__)
-  InstructionSet instruction_set = kX86;
-#elif defined(__x86_64__)
-  InstructionSet instruction_set = kX86_64;
-#elif defined(__mips__)
-  InstructionSet instruction_set = kMips;
-#else
-  InstructionSet instruction_set = kNone;
-#endif
+  InstructionSet instruction_set = kRuntimeISA;
 
   // Profile file to use
   std::string profile_file;
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index 0c8a4f0..01ca60f 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -22,6 +22,7 @@
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "utils.h"
+#include "instruction_set.h"
 
 namespace art {
 
@@ -773,6 +774,40 @@
 
 bool ElfFile::Load(bool executable, std::string* error_msg) {
   CHECK(program_header_only_) << file_->GetPath();
+
+  if (executable) {
+    InstructionSet elf_ISA = kNone;
+    switch (GetHeader().e_machine) {
+      case EM_ARM: {
+        elf_ISA = kArm;
+        break;
+      }
+      case EM_AARCH64: {
+        elf_ISA = kArm64;
+        break;
+      }
+      case EM_386: {
+        elf_ISA = kX86;
+        break;
+      }
+      case EM_X86_64: {
+        elf_ISA = kX86_64;
+        break;
+      }
+      case EM_MIPS: {
+        elf_ISA = kMips;
+        break;
+      }
+    }
+
+    if (elf_ISA != kRuntimeISA) {
+      std::ostringstream oss;
+      oss << "Expected ISA " << kRuntimeISA << " but found " << elf_ISA;
+      *error_msg = oss.str();
+      return false;
+    }
+  }
+
   for (Elf32_Word i = 0; i < GetProgramHeaderNum(); i++) {
     Elf32_Phdr& program_header = GetProgramHeader(i);
 
diff --git a/runtime/instruction_set.h b/runtime/instruction_set.h
index c5a4ec8..f4eecfc 100644
--- a/runtime/instruction_set.h
+++ b/runtime/instruction_set.h
@@ -35,6 +35,20 @@
 };
 std::ostream& operator<<(std::ostream& os, const InstructionSet& rhs);
 
+#if defined(__arm__)
+static constexpr InstructionSet kRuntimeISA = kArm;
+#elif defined(__aarch64__)
+static constexpr InstructionSet kRuntimeISA = kArm64;
+#elif defined(__mips__)
+static constexpr InstructionSet kRuntimeISA = kMips;
+#elif defined(__i386__)
+static constexpr InstructionSet kRuntimeISA = kX86;
+#elif defined(__x86_64__)
+static constexpr InstructionSet kRuntimeISA = kX86_64;
+#else
+static constexpr InstructionSet kRuntimeISA = kNone;
+#endif
+
 enum InstructionFeatures {
   kHwDiv = 1                  // Supports hardware divide.
 };