Merge "Do not mark pages executable unnecessarily to play nice with selinux"
diff --git a/compiler/elf_writer_test.cc b/compiler/elf_writer_test.cc
index d4486d2..4a02b61 100644
--- a/compiler/elf_writer_test.cc
+++ b/compiler/elf_writer_test.cc
@@ -82,7 +82,7 @@
   {
     UniquePtr<ElfFile> ef(ElfFile::Open(file.get(), false, true));
     CHECK(ef.get() != NULL);
-    ef->Load();
+    ef->Load(false);
     EXPECT_EQ(dl_oatdata, ef->FindDynamicSymbolAddress("oatdata"));
     EXPECT_EQ(dl_oatexec, ef->FindDynamicSymbolAddress("oatexec"));
     EXPECT_EQ(dl_oatlastword, ef->FindDynamicSymbolAddress("oatlastword"));
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index f9caa9d..fd0bf2f 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -1416,7 +1416,7 @@
 
   if (oat_filename != NULL) {
     OatFile* oat_file =
-        OatFile::Open(oat_filename, oat_filename, NULL);
+        OatFile::Open(oat_filename, oat_filename, NULL, false);
     if (oat_file == NULL) {
       fprintf(stderr, "Failed to open oat file from %s\n", oat_filename);
       return EXIT_FAILURE;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 8ea4295..e35b95c 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -692,7 +692,8 @@
   oat_filename += runtime->GetHostPrefix();
   oat_filename += oat_location->ToModifiedUtf8();
   runtime->GetHeap()->UnReserveOatFileAddressRange();
-  OatFile* oat_file = OatFile::Open(oat_filename, oat_filename, image_header.GetOatDataBegin());
+  OatFile* oat_file = OatFile::Open(oat_filename, oat_filename, image_header.GetOatDataBegin(),
+                                    !Runtime::Current()->IsCompiler());
   VLOG(startup) << "ClassLinker::OpenOat entering oat_filename=" << oat_filename;
   if (oat_file == NULL) {
     LOG(ERROR) << "Failed to open oat file " << oat_filename << " referenced from image.";
@@ -731,7 +732,8 @@
 const DexFile* ClassLinker::FindDexFileInOatLocation(const std::string& dex_location,
                                                      uint32_t dex_location_checksum,
                                                      const std::string& oat_location) {
-  UniquePtr<OatFile> oat_file(OatFile::Open(oat_location, oat_location, NULL));
+  UniquePtr<OatFile> oat_file(OatFile::Open(oat_location, oat_location, NULL,
+                                            !Runtime::Current()->IsCompiler()));
   if (oat_file.get() == NULL) {
     return NULL;
   }
@@ -787,7 +789,8 @@
     LOG(ERROR) << "Failed to generate oat file: " << oat_location;
     return NULL;
   }
-  const OatFile* oat_file = OatFile::Open(oat_location, oat_location, NULL);
+  const OatFile* oat_file = OatFile::Open(oat_location, oat_location, NULL,
+                                          !Runtime::Current()->IsCompiler());
   if (oat_file == NULL) {
     LOG(ERROR) << "Failed to open generated oat file: " << oat_location;
     return NULL;
@@ -936,7 +939,7 @@
     return oat_file;
   }
 
-  oat_file = OatFile::Open(oat_location, oat_location, NULL);
+  oat_file = OatFile::Open(oat_location, oat_location, NULL, !Runtime::Current()->IsCompiler());
   if (oat_file == NULL) {
     return NULL;
   }
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index cb4ef81..da122e6 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -587,7 +587,7 @@
   return loaded_size;
 }
 
-bool ElfFile::Load() {
+bool ElfFile::Load(bool executable) {
   // TODO: actually return false error
   CHECK(program_header_only_) << file_->GetPath();
   for (llvm::ELF::Elf32_Word i = 0; i < GetProgramHeaderNum(); i++) {
@@ -630,7 +630,7 @@
     }
     byte* p_vaddr = base_address_ + program_header.p_vaddr;
     int prot = 0;
-    if ((program_header.p_flags & llvm::ELF::PF_X) != 0) {
+    if (executable && ((program_header.p_flags & llvm::ELF::PF_X) != 0)) {
       prot |= PROT_EXEC;
     }
     if ((program_header.p_flags & llvm::ELF::PF_W) != 0) {
diff --git a/runtime/elf_file.h b/runtime/elf_file.h
index 59ce7f5..cb95cb0 100644
--- a/runtime/elf_file.h
+++ b/runtime/elf_file.h
@@ -113,8 +113,9 @@
   // Returns the expected size when the file is loaded at runtime
   size_t GetLoadedSize();
 
-  // Load segments into memory based on PT_LOAD program headers
-  bool Load();
+  // Load segments into memory based on PT_LOAD program headers.
+  // executable is true at run time, false at compile time.
+  bool Load(bool executable);
 
  private:
   ElfFile();
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index b9838f8..dc3573d 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -212,7 +212,7 @@
 
   // Check if we have an odex file next to the dex file.
   std::string odex_filename(OatFile::DexFilenameToOdexFilename(filename.c_str()));
-  UniquePtr<const OatFile> oat_file(OatFile::Open(odex_filename, odex_filename, NULL));
+  UniquePtr<const OatFile> oat_file(OatFile::Open(odex_filename, odex_filename, NULL, false));
   if (oat_file.get() != NULL) {
     ScopedObjectAccess soa(env);
     const art::OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(filename.c_str());
@@ -242,7 +242,7 @@
 
   // Check if we have an oat file in the cache
   std::string cache_location(GetDalvikCacheFilenameOrDie(filename.c_str()));
-  oat_file.reset(OatFile::Open(cache_location, filename.c_str(), NULL));
+  oat_file.reset(OatFile::Open(cache_location, filename.c_str(), NULL, false));
   if (oat_file.get() == NULL) {
     LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location
               << " does not exist for " << filename.c_str();
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index ebf92a7..0f29915 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -59,29 +59,30 @@
 
 OatFile* OatFile::Open(const std::string& filename,
                        const std::string& location,
-                       byte* requested_base) {
+                       byte* requested_base,
+                       bool executable) {
   CHECK(!filename.empty()) << location;
   CheckLocation(filename);
-  OatFile* result = OpenDlopen(filename, location, requested_base);
-  if (result != NULL) {
-    return result;
+  // If we are trying to execute, we need to use dlopen.
+  if (executable) {
+    return OpenDlopen(filename, location, requested_base);
   }
-  // On target, only used dlopen to load.
-  if (kIsTargetBuild) {
-    return NULL;
-  }
+  // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
+  //
+  // On target, dlopen may fail when compiling due to selinux restrictions on installd.
+  //
   // On host, dlopen is expected to fail when cross compiling, so fall back to OpenElfFile.
   // This won't work for portable runtime execution because it doesn't process relocations.
   UniquePtr<File> file(OS::OpenFile(filename.c_str(), false, false));
   if (file.get() == NULL) {
     return NULL;
   }
-  return OpenElfFile(file.get(), location, requested_base, false);
+  return OpenElfFile(file.get(), location, requested_base, false, executable);
 }
 
 OatFile* OatFile::OpenWritable(File* file, const std::string& location) {
   CheckLocation(location);
-  return OpenElfFile(file, location, NULL, true);
+  return OpenElfFile(file, location, NULL, true, false);
 }
 
 OatFile* OatFile::OpenDlopen(const std::string& elf_filename,
@@ -98,9 +99,10 @@
 OatFile* OatFile::OpenElfFile(File* file,
                               const std::string& location,
                               byte* requested_base,
-                              bool writable) {
+                              bool writable,
+                              bool executable) {
   UniquePtr<OatFile> oat_file(new OatFile(location));
-  bool success = oat_file->ElfFileOpen(file, requested_base, writable);
+  bool success = oat_file->ElfFileOpen(file, requested_base, writable, executable);
   if (!success) {
     return NULL;
   }
@@ -154,13 +156,13 @@
   return Setup();
 }
 
-bool OatFile::ElfFileOpen(File* file, byte* requested_base, bool writable) {
+bool OatFile::ElfFileOpen(File* file, byte* requested_base, bool writable, bool executable) {
   elf_file_.reset(ElfFile::Open(file, writable, true));
   if (elf_file_.get() == NULL) {
     PLOG(WARNING) << "Failed to create ELF file for " << file->GetPath();
     return false;
   }
-  bool loaded = elf_file_->Load();
+  bool loaded = elf_file_->Load(executable);
   if (!loaded) {
     LOG(WARNING) << "Failed to load ELF file " << file->GetPath();
     return false;
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 0bf79a9..e3fd002 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -44,7 +44,8 @@
   // optionally be used to request where the file should be loaded.
   static OatFile* Open(const std::string& filename,
                        const std::string& location,
-                       byte* requested_base);
+                       byte* requested_base,
+                       bool executable);
 
   // Open an oat file from an already opened File.
   // Does not use dlopen underneath so cannot be used for runtime use
@@ -215,11 +216,12 @@
   static OatFile* OpenElfFile(File* file,
                               const std::string& location,
                               byte* requested_base,
-                              bool writable);
+                              bool writable,
+                              bool executable);
 
   explicit OatFile(const std::string& filename);
   bool Dlopen(const std::string& elf_filename, byte* requested_base);
-  bool ElfFileOpen(File* file, byte* requested_base, bool writable);
+  bool ElfFileOpen(File* file, byte* requested_base, bool writable, bool executable);
   bool Setup();
 
   const byte* Begin() const;
diff --git a/runtime/oat_test.cc b/runtime/oat_test.cc
index f41a7ba..70c2e9e 100644
--- a/runtime/oat_test.cc
+++ b/runtime/oat_test.cc
@@ -102,7 +102,7 @@
   if (compile) {  // OatWriter strips the code, regenerate to compare
     compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath());
   }
-  UniquePtr<OatFile> oat_file(OatFile::Open(tmp.GetFilename(), tmp.GetFilename(), NULL));
+  UniquePtr<OatFile> oat_file(OatFile::Open(tmp.GetFilename(), tmp.GetFilename(), NULL, false));
   ASSERT_TRUE(oat_file.get() != NULL);
   const OatHeader& oat_header = oat_file->GetOatHeader();
   ASSERT_TRUE(oat_header.IsValid());