ART: Add pic flag to oat header store
Add the compile-time PIC flag to the oat-header key-value store.
Ignore image offset and patch delta when loading PIC oat files.
(cherry-picked from AOSP master
7ba649636c4475c3992fa15a57acd2546d69ff38)
Bug: 18035729
Signed-off-by: Igor Murashkin <iam@google.com>
Change-Id: Ie1f1ef37125386a968228033d1e2bec565315510
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 6b85558..6a4df49 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -782,7 +782,7 @@
*parsed_value = value;
}
-static int dex2oat(int argc, char** argv) {
+static void b13564922() {
#if defined(__linux__) && defined(__arm__)
int major, minor;
struct utsname uts;
@@ -800,6 +800,10 @@
}
}
#endif
+}
+
+static int dex2oat(int argc, char** argv) {
+ b13564922();
original_argc = argc;
original_argv = argv;
@@ -1386,17 +1390,20 @@
new SafeMap<std::string, std::string>());
// Insert some compiler things.
- std::ostringstream oss;
- for (int i = 0; i < argc; ++i) {
- if (i > 0) {
- oss << ' ';
+ {
+ std::ostringstream oss;
+ for (int i = 0; i < argc; ++i) {
+ if (i > 0) {
+ oss << ' ';
+ }
+ oss << argv[i];
}
- oss << argv[i];
+ key_value_store->Put(OatHeader::kDex2OatCmdLineKey, oss.str());
+ oss.str(""); // Reset.
+ oss << kRuntimeISA;
+ key_value_store->Put(OatHeader::kDex2OatHostKey, oss.str());
+ key_value_store->Put(OatHeader::kPicKey, compile_pic ? "true" : "false");
}
- key_value_store->Put(OatHeader::kDex2OatCmdLineKey, oss.str());
- oss.str(""); // Reset.
- oss << kRuntimeISA;
- key_value_store->Put(OatHeader::kDex2OatHostKey, oss.str());
std::unique_ptr<const CompilerDriver> compiler(dex2oat->CreateOatFile(boot_image_option,
android_root,
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index d8bc204..079d958 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1288,11 +1288,11 @@
bool odex_checksum_verified = false;
bool have_system_odex = false;
{
- // There is a high probability that these both these oat files map similar/the same address
+ // There is a high probability that both these oat files map similar/the same address
// spaces so we must scope them like this so they each gets its turn.
std::unique_ptr<OatFile> odex_oat_file(OatFile::Open(odex_filename, odex_filename, nullptr,
executable, &odex_error_msg));
- if (odex_oat_file.get() != nullptr && CheckOatFile(odex_oat_file.get(), isa,
+ if (odex_oat_file.get() != nullptr && CheckOatFile(runtime, odex_oat_file.get(), isa,
&odex_checksum_verified,
&odex_error_msg)) {
error_msgs->push_back(odex_error_msg);
@@ -1315,7 +1315,7 @@
if (have_dalvik_cache) {
std::unique_ptr<OatFile> cache_oat_file(OatFile::Open(cache_filename, cache_filename, nullptr,
executable, &cache_error_msg));
- if (cache_oat_file.get() != nullptr && CheckOatFile(cache_oat_file.get(), isa,
+ if (cache_oat_file.get() != nullptr && CheckOatFile(runtime, cache_oat_file.get(), isa,
&cache_checksum_verified,
&cache_error_msg)) {
error_msgs->push_back(cache_error_msg);
@@ -1410,13 +1410,15 @@
const std::string& image_location,
InstructionSet isa,
std::string* error_msg) {
- if (!Runtime::Current()->GetHeap()->HasImageSpace()) {
+ Runtime* runtime = Runtime::Current();
+ DCHECK(runtime != nullptr);
+ if (!runtime->GetHeap()->HasImageSpace()) {
// We don't have an image space so there is no point in trying to patchoat.
LOG(WARNING) << "Patching of oat file '" << input_oat << "' not attempted because we are "
<< "running without an image. Attempting to use oat file for interpretation.";
return GetInterpretedOnlyOat(input_oat, isa, error_msg);
}
- if (!Runtime::Current()->IsDex2OatEnabled()) {
+ if (!runtime->IsDex2OatEnabled()) {
// We don't have dex2oat so we can assume we don't have patchoat either. We should just use the
// input_oat but make sure we only do interpretation on it's dex files.
LOG(WARNING) << "Patching of oat file '" << input_oat << "' not attempted due to dex2oat being "
@@ -1424,7 +1426,7 @@
return GetInterpretedOnlyOat(input_oat, isa, error_msg);
}
Locks::mutator_lock_->AssertNotHeld(Thread::Current()); // Avoid starving GC.
- std::string patchoat(Runtime::Current()->GetPatchoatExecutable());
+ std::string patchoat(runtime->GetPatchoatExecutable());
std::string isa_arg("--instruction-set=");
isa_arg += GetInstructionSetString(isa);
@@ -1447,9 +1449,10 @@
bool success = Exec(argv, error_msg);
if (success) {
std::unique_ptr<OatFile> output(OatFile::Open(output_oat, output_oat, nullptr,
- !Runtime::Current()->IsCompiler(), error_msg));
+ !runtime->IsCompiler(), error_msg));
bool checksum_verified = false;
- if (output.get() != nullptr && CheckOatFile(output.get(), isa, &checksum_verified, error_msg)) {
+ if (output.get() != nullptr && CheckOatFile(runtime, output.get(), isa, &checksum_verified,
+ error_msg)) {
return output.release();
} else if (output.get() != nullptr) {
*error_msg = StringPrintf("Patching of oat file '%s' succeeded "
@@ -1460,7 +1463,7 @@
"but was unable to open output file '%s': %s",
input_oat.c_str(), output_oat.c_str(), error_msg->c_str());
}
- } else if (!Runtime::Current()->IsCompiler()) {
+ } else if (!runtime->IsCompiler()) {
// patchoat failed which means we probably don't have enough room to place the output oat file,
// instead of failing we should just run the interpreter from the dex files in the input oat.
LOG(WARNING) << "Patching of oat file '" << input_oat << "' failed. Attempting to use oat file "
@@ -1474,32 +1477,14 @@
return nullptr;
}
-int32_t ClassLinker::GetRequiredDelta(const OatFile* oat_file, InstructionSet isa) {
- Runtime* runtime = Runtime::Current();
- int32_t real_patch_delta;
- const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetImageSpace();
- CHECK(image_space != nullptr);
- if (isa == Runtime::Current()->GetInstructionSet()) {
- const ImageHeader& image_header = image_space->GetImageHeader();
- real_patch_delta = image_header.GetPatchDelta();
- } else {
- std::unique_ptr<ImageHeader> image_header(gc::space::ImageSpace::ReadImageHeaderOrDie(
- image_space->GetImageLocation().c_str(), isa));
- real_patch_delta = image_header->GetPatchDelta();
- }
- const OatHeader& oat_header = oat_file->GetOatHeader();
- return real_patch_delta - oat_header.GetImagePatchDelta();
-}
-
-bool ClassLinker::CheckOatFile(const OatFile* oat_file, InstructionSet isa,
+bool ClassLinker::CheckOatFile(const Runtime* runtime, const OatFile* oat_file, InstructionSet isa,
bool* checksum_verified,
std::string* error_msg) {
std::string compound_msg("Oat file failed to verify: ");
- Runtime* runtime = Runtime::Current();
uint32_t real_image_checksum;
void* real_image_oat_offset;
int32_t real_patch_delta;
- const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetImageSpace();
+ const gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetImageSpace();
if (image_space == nullptr) {
*error_msg = "No image space present";
return false;
@@ -1526,19 +1511,28 @@
real_image_checksum, oat_image_checksum);
}
- void* oat_image_oat_offset =
- reinterpret_cast<void*>(oat_header.GetImageFileLocationOatDataBegin());
- bool offset_verified = oat_image_oat_offset == real_image_oat_offset;
- if (!offset_verified) {
- compound_msg += StringPrintf(" Oat Image oat offset incorrect (expected 0x%p, recieved 0x%p)",
- real_image_oat_offset, oat_image_oat_offset);
- }
+ bool offset_verified;
+ bool patch_delta_verified;
- int32_t oat_patch_delta = oat_header.GetImagePatchDelta();
- bool patch_delta_verified = oat_patch_delta == real_patch_delta;
- if (!patch_delta_verified) {
- compound_msg += StringPrintf(" Oat image patch delta incorrect (expected 0x%x, recieved 0x%x)",
- real_patch_delta, oat_patch_delta);
+ if (!oat_file->IsPic()) {
+ void* oat_image_oat_offset =
+ reinterpret_cast<void*>(oat_header.GetImageFileLocationOatDataBegin());
+ offset_verified = oat_image_oat_offset == real_image_oat_offset;
+ if (!offset_verified) {
+ compound_msg += StringPrintf(" Oat Image oat offset incorrect (expected 0x%p, recieved 0x%p)",
+ real_image_oat_offset, oat_image_oat_offset);
+ }
+
+ int32_t oat_patch_delta = oat_header.GetImagePatchDelta();
+ patch_delta_verified = oat_patch_delta == real_patch_delta;
+ if (!patch_delta_verified) {
+ compound_msg += StringPrintf(" Oat image patch delta incorrect (expected 0x%x, recieved 0x%x)",
+ real_patch_delta, oat_patch_delta);
+ }
+ } else {
+ // If an oat file is PIC, we ignore offset and patching delta.
+ offset_verified = true;
+ patch_delta_verified = true;
}
bool ret = (*checksum_verified && offset_verified && patch_delta_verified);
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 3afbac0..9e86aa2 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -49,8 +49,8 @@
class InternTable;
template<class T> class ObjectLock;
+class Runtime;
class ScopedObjectAccessAlreadyRunnable;
-template<class T> class Handle;
template<size_t kNumReferences> class PACKED(4) StackHandleScope;
typedef bool (ClassVisitor)(mirror::Class* c, void* arg);
@@ -589,9 +589,8 @@
std::string* error_msg)
LOCKS_EXCLUDED(Locks::mutator_lock_);
- bool CheckOatFile(const OatFile* oat_file, InstructionSet isa,
+ bool CheckOatFile(const Runtime* runtime, const OatFile* oat_file, InstructionSet isa,
bool* checksum_verified, std::string* error_msg);
- int32_t GetRequiredDelta(const OatFile* oat_file, InstructionSet isa);
// Note: will not register the oat file.
const OatFile* FindOatFileInOatLocationForDexFile(const char* dex_location,
diff --git a/runtime/oat.h b/runtime/oat.h
index 6d5fefe..139f1cc 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -35,6 +35,7 @@
static constexpr const char* kImageLocationKey = "image-location";
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
static constexpr const char* kDex2OatHostKey = "dex2oat-host";
+ static constexpr const char* kPicKey = "pic";
static OatHeader* Create(InstructionSet instruction_set,
const InstructionSetFeatures& instruction_set_features,
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 025f87d..be50199 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -70,7 +70,7 @@
bool executable,
std::string* error_msg) {
CHECK(!filename.empty()) << location;
- CheckLocation(filename);
+ CheckLocation(location);
std::unique_ptr<OatFile> ret;
if (kUsePortableCompiler && executable) {
// If we are using PORTABLE, use dlopen to deal with relocations.
@@ -599,4 +599,10 @@
method->SetNativeGcMap(GetNativeGcMap());
}
+bool OatFile::IsPic() const {
+ const char* pic_string = GetOatHeader().GetStoreValueByKey(OatHeader::kPicKey);
+ return (pic_string != nullptr && strncmp(pic_string, "true", 5) == 0);
+ // TODO: Check against oat_patches. b/18144996
+}
+
} // namespace art
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index e5cd6ec..a4c8da9 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -72,6 +72,8 @@
return is_executable_;
}
+ bool IsPic() const;
+
ElfFile* GetElfFile() const {
CHECK_NE(reinterpret_cast<uintptr_t>(elf_file_.get()), reinterpret_cast<uintptr_t>(nullptr))
<< "Cannot get an elf file from " << GetLocation();