Add oatdump support for app images
Example usage on host:
oatdumpd --app-oat=art/plus32.odex --app-image=art/plus32.art
--image=art/oats/system@framework@boot.art --instruction-set=arm
TODO: Add to oatdump test.
Bug: 27408512
Bug: 22858531
(cherry picked from commit bcb6a72569a1401b36a3ad3b6aa4d13e29966cf0)
Change-Id: I9d1aa7eaa16795e5fbabc6974d245849e16b1d03
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index ebe89bb..8541210 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -473,39 +473,40 @@
}
template <typename Visitor>
-inline void ArtMethod::UpdateObjectsForImageRelocation(const Visitor& visitor) {
+inline void ArtMethod::UpdateObjectsForImageRelocation(const Visitor& visitor,
+ size_t pointer_size) {
mirror::Class* old_class = GetDeclaringClassUnchecked<kWithoutReadBarrier>();
mirror::Class* new_class = visitor(old_class);
if (old_class != new_class) {
SetDeclaringClass(new_class);
}
- ArtMethod** old_methods = GetDexCacheResolvedMethods(sizeof(void*));
+ ArtMethod** old_methods = GetDexCacheResolvedMethods(pointer_size);
ArtMethod** new_methods = visitor(old_methods);
if (old_methods != new_methods) {
- SetDexCacheResolvedMethods(new_methods, sizeof(void*));
+ SetDexCacheResolvedMethods(new_methods, pointer_size);
}
- GcRoot<mirror::Class>* old_types = GetDexCacheResolvedTypes(sizeof(void*));
+ GcRoot<mirror::Class>* old_types = GetDexCacheResolvedTypes(pointer_size);
GcRoot<mirror::Class>* new_types = visitor(old_types);
if (old_types != new_types) {
- SetDexCacheResolvedTypes(new_types, sizeof(void*));
+ SetDexCacheResolvedTypes(new_types, pointer_size);
}
}
template <ReadBarrierOption kReadBarrierOption, typename Visitor>
-inline void ArtMethod::UpdateEntrypoints(const Visitor& visitor) {
+inline void ArtMethod::UpdateEntrypoints(const Visitor& visitor, size_t pointer_size) {
if (IsNative<kReadBarrierOption>()) {
- const void* old_native_code = GetEntryPointFromJni();
+ const void* old_native_code = GetEntryPointFromJniPtrSize(pointer_size);
const void* new_native_code = visitor(old_native_code);
if (old_native_code != new_native_code) {
- SetEntryPointFromJni(new_native_code);
+ SetEntryPointFromJniPtrSize(new_native_code, pointer_size);
}
} else {
- DCHECK(GetEntryPointFromJni() == nullptr);
+ DCHECK(GetEntryPointFromJniPtrSize(pointer_size) == nullptr);
}
- const void* old_code = GetEntryPointFromQuickCompiledCode();
+ const void* old_code = GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
const void* new_code = visitor(old_code);
if (old_code != new_code) {
- SetEntryPointFromQuickCompiledCode(new_code);
+ SetEntryPointFromQuickCompiledCodePtrSize(new_code, pointer_size);
}
}
diff --git a/runtime/art_method.h b/runtime/art_method.h
index ec00a7b..5ca362c 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -490,12 +490,12 @@
// Update heap objects and non-entrypoint pointers by the passed in visitor for image relocation.
// Does not use read barrier.
template <typename Visitor>
- ALWAYS_INLINE void UpdateObjectsForImageRelocation(const Visitor& visitor)
+ ALWAYS_INLINE void UpdateObjectsForImageRelocation(const Visitor& visitor, size_t pointer_size)
SHARED_REQUIRES(Locks::mutator_lock_);
// Update entry points by passing them through the visitor.
template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
- ALWAYS_INLINE void UpdateEntrypoints(const Visitor& visitor);
+ ALWAYS_INLINE void UpdateEntrypoints(const Visitor& visitor, size_t pointer_size);
protected:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index d51a1f7..52beb15 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1462,6 +1462,64 @@
const bool forward_strings_;
};
+static std::unique_ptr<const DexFile> OpenOatDexFile(const OatFile* oat_file,
+ const char* location,
+ std::string* error_msg)
+ SHARED_REQUIRES(Locks::mutator_lock_) {
+ DCHECK(error_msg != nullptr);
+ std::unique_ptr<const DexFile> dex_file;
+ const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(location, nullptr);
+ if (oat_dex_file == nullptr) {
+ *error_msg = StringPrintf("Failed finding oat dex file for %s %s",
+ oat_file->GetLocation().c_str(),
+ location);
+ return std::unique_ptr<const DexFile>();
+ }
+ std::string inner_error_msg;
+ dex_file = oat_dex_file->OpenDexFile(&inner_error_msg);
+ if (dex_file == nullptr) {
+ *error_msg = StringPrintf("Failed to open dex file %s from within oat file %s error '%s'",
+ location,
+ oat_file->GetLocation().c_str(),
+ inner_error_msg.c_str());
+ return std::unique_ptr<const DexFile>();
+ }
+
+ if (dex_file->GetLocationChecksum() != oat_dex_file->GetDexFileLocationChecksum()) {
+ *error_msg = StringPrintf("Checksums do not match for %s: %x vs %x",
+ location,
+ dex_file->GetLocationChecksum(),
+ oat_dex_file->GetDexFileLocationChecksum());
+ return std::unique_ptr<const DexFile>();
+ }
+ return dex_file;
+}
+
+bool ClassLinker::OpenImageDexFiles(gc::space::ImageSpace* space,
+ std::vector<std::unique_ptr<const DexFile>>* out_dex_files,
+ std::string* error_msg) {
+ ScopedAssertNoThreadSuspension nts(Thread::Current(), __FUNCTION__);
+ const ImageHeader& header = space->GetImageHeader();
+ mirror::Object* dex_caches_object = header.GetImageRoot(ImageHeader::kDexCaches);
+ DCHECK(dex_caches_object != nullptr);
+ mirror::ObjectArray<mirror::DexCache>* dex_caches =
+ dex_caches_object->AsObjectArray<mirror::DexCache>();
+ const OatFile* oat_file = space->GetOatFile();
+ for (int32_t i = 0; i < dex_caches->GetLength(); i++) {
+ mirror::DexCache* dex_cache = dex_caches->Get(i);
+ std::string dex_file_location(dex_cache->GetLocation()->ToModifiedUtf8());
+ std::unique_ptr<const DexFile> dex_file = OpenOatDexFile(oat_file,
+ dex_file_location.c_str(),
+ error_msg);
+ if (dex_file == nullptr) {
+ return false;
+ }
+ dex_cache->SetDexFile(dex_file.get());
+ out_dex_files->push_back(std::move(dex_file));
+ }
+ return true;
+}
+
bool ClassLinker::AddImageSpace(
gc::space::ImageSpace* space,
Handle<mirror::ClassLoader> class_loader,
@@ -1528,29 +1586,10 @@
dex_location_path = dex_location_path.substr(0, pos + 1); // Keep trailing '/'
dex_file_location = dex_location_path + dex_file_location;
}
- const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file_location.c_str(),
- nullptr);
- if (oat_dex_file == nullptr) {
- *error_msg = StringPrintf("Failed finding oat dex file for %s %s",
- oat_file->GetLocation().c_str(),
- dex_file_location.c_str());
- return false;
- }
- std::string inner_error_msg;
- std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&inner_error_msg);
+ std::unique_ptr<const DexFile> dex_file = OpenOatDexFile(oat_file,
+ dex_file_location.c_str(),
+ error_msg);
if (dex_file == nullptr) {
- *error_msg = StringPrintf("Failed to open dex file %s from within oat file %s error '%s'",
- dex_file_location.c_str(),
- oat_file->GetLocation().c_str(),
- inner_error_msg.c_str());
- return false;
- }
-
- if (dex_file->GetLocationChecksum() != oat_dex_file->GetDexFileLocationChecksum()) {
- *error_msg = StringPrintf("Checksums do not match for %s: %x vs %x",
- dex_file_location.c_str(),
- dex_file->GetLocationChecksum(),
- oat_dex_file->GetDexFileLocationChecksum());
return false;
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 492a228..36ed820 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -149,6 +149,12 @@
REQUIRES(!dex_lock_)
SHARED_REQUIRES(Locks::mutator_lock_);
+ bool OpenImageDexFiles(gc::space::ImageSpace* space,
+ std::vector<std::unique_ptr<const DexFile>>* out_dex_files,
+ std::string* error_msg)
+ REQUIRES(!dex_lock_)
+ SHARED_REQUIRES(Locks::mutator_lock_);
+
// Finds a class by its descriptor, loading it if necessary.
// If class_loader is null, searches boot_class_path_.
mirror::Class* FindClass(Thread* self,
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index 52da28b..3b4b88d 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -57,9 +57,12 @@
}
template <typename ElfTypes>
-ElfFileImpl<ElfTypes>* ElfFileImpl<ElfTypes>::Open(
- File* file, bool writable, bool program_header_only,
- std::string* error_msg, uint8_t* requested_base) {
+ElfFileImpl<ElfTypes>* ElfFileImpl<ElfTypes>::Open(File* file,
+ bool writable,
+ bool program_header_only,
+ bool low_4gb,
+ std::string* error_msg,
+ uint8_t* requested_base) {
std::unique_ptr<ElfFileImpl<ElfTypes>> elf_file(new ElfFileImpl<ElfTypes>
(file, writable, program_header_only, requested_base));
int prot;
@@ -71,26 +74,29 @@
prot = PROT_READ;
flags = MAP_PRIVATE;
}
- if (!elf_file->Setup(prot, flags, error_msg)) {
+ if (!elf_file->Setup(prot, flags, low_4gb, error_msg)) {
return nullptr;
}
return elf_file.release();
}
template <typename ElfTypes>
-ElfFileImpl<ElfTypes>* ElfFileImpl<ElfTypes>::Open(
- File* file, int prot, int flags, std::string* error_msg) {
+ElfFileImpl<ElfTypes>* ElfFileImpl<ElfTypes>::Open(File* file,
+ int prot,
+ int flags,
+ bool low_4gb,
+ std::string* error_msg) {
std::unique_ptr<ElfFileImpl<ElfTypes>> elf_file(new ElfFileImpl<ElfTypes>
(file, (prot & PROT_WRITE) == PROT_WRITE, /*program_header_only*/false,
/*requested_base*/nullptr));
- if (!elf_file->Setup(prot, flags, error_msg)) {
+ if (!elf_file->Setup(prot, flags, low_4gb, error_msg)) {
return nullptr;
}
return elf_file.release();
}
template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::Setup(int prot, int flags, std::string* error_msg) {
+bool ElfFileImpl<ElfTypes>::Setup(int prot, int flags, bool low_4gb, std::string* error_msg) {
int64_t temp_file_length = file_->GetLength();
if (temp_file_length < 0) {
errno = -temp_file_length;
@@ -114,7 +120,7 @@
flags,
file_->Fd(),
0,
- /*low4_gb*/false,
+ low_4gb,
file_->GetPath().c_str(),
error_msg),
error_msg)) {
@@ -133,7 +139,7 @@
flags,
file_->Fd(),
0,
- /*low4_gb*/false,
+ low_4gb,
file_->GetPath().c_str(),
error_msg),
error_msg)) {
@@ -147,7 +153,7 @@
flags,
file_->Fd(),
0,
- /*low4_gb*/false,
+ low_4gb,
file_->GetPath().c_str(),
error_msg),
error_msg)) {
@@ -1058,7 +1064,7 @@
}
template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::Load(bool executable, std::string* error_msg) {
+bool ElfFileImpl<ElfTypes>::Load(bool executable, bool low_4gb, std::string* error_msg) {
CHECK(program_header_only_) << file_->GetPath();
if (executable) {
@@ -1124,7 +1130,10 @@
}
std::unique_ptr<MemMap> reserve(MemMap::MapAnonymous(reservation_name.c_str(),
reserve_base_override,
- loaded_size, PROT_NONE, false, false,
+ loaded_size,
+ PROT_NONE,
+ low_4gb,
+ false,
error_msg));
if (reserve.get() == nullptr) {
*error_msg = StringPrintf("Failed to allocate %s: %s",
@@ -1656,7 +1665,11 @@
CHECK_NE(elf32_.get() == nullptr, elf64_.get() == nullptr);
}
-ElfFile* ElfFile::Open(File* file, bool writable, bool program_header_only, std::string* error_msg,
+ElfFile* ElfFile::Open(File* file,
+ bool writable,
+ bool program_header_only,
+ bool low_4gb,
+ std::string* error_msg,
uint8_t* requested_base) {
if (file->GetLength() < EI_NIDENT) {
*error_msg = StringPrintf("File %s is too short to be a valid ELF file",
@@ -1668,7 +1681,7 @@
MAP_PRIVATE,
file->Fd(),
0,
- /*low4_gb*/false,
+ low_4gb,
file->GetPath().c_str(),
error_msg));
if (map == nullptr && map->Size() != EI_NIDENT) {
@@ -1676,14 +1689,22 @@
}
uint8_t* header = map->Begin();
if (header[EI_CLASS] == ELFCLASS64) {
- ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file, writable, program_header_only,
- error_msg, requested_base);
+ ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file,
+ writable,
+ program_header_only,
+ low_4gb,
+ error_msg,
+ requested_base);
if (elf_file_impl == nullptr)
return nullptr;
return new ElfFile(elf_file_impl);
} else if (header[EI_CLASS] == ELFCLASS32) {
- ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file, writable, program_header_only,
- error_msg, requested_base);
+ ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file,
+ writable,
+ program_header_only,
+ low_4gb,
+ error_msg,
+ requested_base);
if (elf_file_impl == nullptr) {
return nullptr;
}
@@ -1698,6 +1719,8 @@
}
ElfFile* ElfFile::Open(File* file, int mmap_prot, int mmap_flags, std::string* error_msg) {
+ // low_4gb support not required for this path.
+ constexpr bool low_4gb = false;
if (file->GetLength() < EI_NIDENT) {
*error_msg = StringPrintf("File %s is too short to be a valid ELF file",
file->GetPath().c_str());
@@ -1708,7 +1731,7 @@
MAP_PRIVATE,
file->Fd(),
0,
- /*low4_gb*/false,
+ low_4gb,
file->GetPath().c_str(),
error_msg));
if (map == nullptr && map->Size() != EI_NIDENT) {
@@ -1716,13 +1739,21 @@
}
uint8_t* header = map->Begin();
if (header[EI_CLASS] == ELFCLASS64) {
- ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file, mmap_prot, mmap_flags, error_msg);
+ ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file,
+ mmap_prot,
+ mmap_flags,
+ low_4gb,
+ error_msg);
if (elf_file_impl == nullptr) {
return nullptr;
}
return new ElfFile(elf_file_impl);
} else if (header[EI_CLASS] == ELFCLASS32) {
- ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file, mmap_prot, mmap_flags, error_msg);
+ ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file,
+ mmap_prot,
+ mmap_flags,
+ low_4gb,
+ error_msg);
if (elf_file_impl == nullptr) {
return nullptr;
}
@@ -1744,8 +1775,8 @@
return elf32_->func(__VA_ARGS__); \
}
-bool ElfFile::Load(bool executable, std::string* error_msg) {
- DELEGATE_TO_IMPL(Load, executable, error_msg);
+bool ElfFile::Load(bool executable, bool low_4gb, std::string* error_msg) {
+ DELEGATE_TO_IMPL(Load, executable, low_4gb, error_msg);
}
const uint8_t* ElfFile::FindDynamicSymbolAddress(const std::string& symbol_name) const {
@@ -1810,7 +1841,7 @@
}
bool ElfFile::Strip(File* file, std::string* error_msg) {
- std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, error_msg));
+ std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, /*low_4gb*/false, error_msg));
if (elf_file.get() == nullptr) {
return false;
}
diff --git a/runtime/elf_file.h b/runtime/elf_file.h
index 1188c97..b5229b5 100644
--- a/runtime/elf_file.h
+++ b/runtime/elf_file.h
@@ -38,15 +38,22 @@
// ELFObjectFile.
class ElfFile {
public:
- static ElfFile* Open(File* file, bool writable, bool program_header_only, std::string* error_msg,
+ static ElfFile* Open(File* file,
+ bool writable,
+ bool program_header_only,
+ bool low_4gb,
+ std::string* error_msg,
uint8_t* requested_base = nullptr); // TODO: move arg to before error_msg.
// Open with specific mmap flags, Always maps in the whole file, not just the
// program header sections.
- static ElfFile* Open(File* file, int mmap_prot, int mmap_flags, std::string* error_msg);
+ static ElfFile* Open(File* file,
+ int mmap_prot,
+ int mmap_flags,
+ std::string* error_msg);
~ElfFile();
// Load segments into memory based on PT_LOAD program headers
- bool Load(bool executable, std::string* error_msg);
+ bool Load(bool executable, bool low_4gb, std::string* error_msg);
const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name) const;
diff --git a/runtime/elf_file_impl.h b/runtime/elf_file_impl.h
index 2af31dc..1cdbedc 100644
--- a/runtime/elf_file_impl.h
+++ b/runtime/elf_file_impl.h
@@ -48,9 +48,17 @@
using Elf_Phdr = typename ElfTypes::Phdr;
using Elf_Dyn = typename ElfTypes::Dyn;
- static ElfFileImpl* Open(File* file, bool writable, bool program_header_only,
- std::string* error_msg, uint8_t* requested_base = nullptr);
- static ElfFileImpl* Open(File* file, int mmap_prot, int mmap_flags, std::string* error_msg);
+ static ElfFileImpl* Open(File* file,
+ bool writable,
+ bool program_header_only,
+ bool low_4gb,
+ std::string* error_msg,
+ uint8_t* requested_base = nullptr);
+ static ElfFileImpl* Open(File* file,
+ int mmap_prot,
+ int mmap_flags,
+ bool low_4gb,
+ std::string* error_msg);
~ElfFileImpl();
const File& GetFile() const {
@@ -111,7 +119,7 @@
// Load segments into memory based on PT_LOAD program headers.
// executable is true at run time, false at compile time.
- bool Load(bool executable, std::string* error_msg);
+ bool Load(bool executable, bool low_4gb, std::string* error_msg);
bool Fixup(Elf_Addr base_address);
bool FixupDynamic(Elf_Addr base_address);
@@ -129,7 +137,7 @@
private:
ElfFileImpl(File* file, bool writable, bool program_header_only, uint8_t* requested_base);
- bool Setup(int prot, int flags, std::string* error_msg);
+ bool Setup(int prot, int flags, bool low_4gb, std::string* error_msg);
bool SetMap(MemMap* map, std::string* error_msg);
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index bea1dcc..895d3d3 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -617,7 +617,7 @@
}
// Returns the delta between the dest from the source.
- off_t Delta() const {
+ uintptr_t Delta() const {
return dest_ - source_;
}
@@ -639,6 +639,13 @@
const uintptr_t length_;
};
+std::ostream& operator<<(std::ostream& os, const RelocationRange& reloc) {
+ return os << "(" << reinterpret_cast<const void*>(reloc.Source()) << "-"
+ << reinterpret_cast<const void*>(reloc.Source() + reloc.Length()) << ")->("
+ << reinterpret_cast<const void*>(reloc.Dest()) << "-"
+ << reinterpret_cast<const void*>(reloc.Dest() + reloc.Length()) << ")";
+}
+
class FixupVisitor : public ValueObject {
public:
FixupVisitor(const RelocationRange& boot_image,
@@ -670,7 +677,7 @@
ALWAYS_INLINE const void* ForwardCode(const void* src) const {
const uintptr_t uint_src = reinterpret_cast<uintptr_t>(src);
if (boot_oat_.InSource(uint_src)) {
- return reinterpret_cast<const void*>(boot_oat_.ToDest(uint_src));
+ return reinterpret_cast<const void*>(boot_oat_.ToDest(uint_src));
}
if (app_oat_.InSource(uint_src)) {
return reinterpret_cast<const void*>(app_oat_.ToDest(uint_src));
@@ -687,13 +694,6 @@
const RelocationRange app_oat_;
};
-std::ostream& operator<<(std::ostream& os, const RelocationRange& reloc) {
- return os << "(" << reinterpret_cast<const void*>(reloc.Source()) << "-"
- << reinterpret_cast<const void*>(reloc.Source() + reloc.Length()) << ")->("
- << reinterpret_cast<const void*>(reloc.Dest()) << "-"
- << reinterpret_cast<const void*>(reloc.Dest() + reloc.Length()) << ")";
-}
-
// Adapt for mirror::Class::FixupNativePointers.
class FixupObjectAdapter : public FixupVisitor {
public:
@@ -756,8 +756,10 @@
public:
template<typename... Args>
explicit FixupObjectVisitor(gc::accounting::ContinuousSpaceBitmap* pointer_array_visited,
+ const size_t pointer_size,
Args... args)
: FixupVisitor(args...),
+ pointer_size_(pointer_size),
pointer_array_visited_(pointer_array_visited) {}
// Fix up separately since we also need to fix up method entrypoints.
@@ -791,7 +793,7 @@
if (array != nullptr &&
visitor.IsInAppImage(array) &&
!pointer_array_visited_->Test(array)) {
- array->Fixup<kVerifyNone, kWithoutReadBarrier>(array, sizeof(void*), visitor);
+ array->Fixup<kVerifyNone, kWithoutReadBarrier>(array, pointer_size_, visitor);
pointer_array_visited_->Set(array);
}
}
@@ -813,7 +815,7 @@
if (obj->IsClass<kVerifyNone, kWithoutReadBarrier>()) {
mirror::Class* klass = obj->AsClass<kVerifyNone, kWithoutReadBarrier>();
FixupObjectAdapter visitor(boot_image_, boot_oat_, app_image_, app_oat_);
- klass->FixupNativePointers<kVerifyNone, kWithoutReadBarrier>(klass, sizeof(void*), visitor);
+ klass->FixupNativePointers<kVerifyNone, kWithoutReadBarrier>(klass, pointer_size_, visitor);
// Deal with the pointer arrays. Use the helper function since multiple classes can reference
// the same arrays.
VisitPointerArray(klass->GetVTable<kVerifyNone, kWithoutReadBarrier>(), visitor);
@@ -832,6 +834,7 @@
}
private:
+ const size_t pointer_size_;
gc::accounting::ContinuousSpaceBitmap* const pointer_array_visited_;
};
@@ -850,7 +853,8 @@
class ForwardCodeAdapter {
public:
- ALWAYS_INLINE ForwardCodeAdapter(const FixupVisitor* visitor) : visitor_(visitor) {}
+ ALWAYS_INLINE ForwardCodeAdapter(const FixupVisitor* visitor)
+ : visitor_(visitor) {}
template <typename T>
ALWAYS_INLINE T* operator()(T* src) const {
@@ -864,19 +868,21 @@
class FixupArtMethodVisitor : public FixupVisitor, public ArtMethodVisitor {
public:
template<typename... Args>
- explicit FixupArtMethodVisitor(bool fixup_heap_objects, Args... args)
+ explicit FixupArtMethodVisitor(bool fixup_heap_objects, size_t pointer_size, Args... args)
: FixupVisitor(args...),
- fixup_heap_objects_(fixup_heap_objects) {}
+ fixup_heap_objects_(fixup_heap_objects),
+ pointer_size_(pointer_size) {}
virtual void Visit(ArtMethod* method) NO_THREAD_SAFETY_ANALYSIS {
if (fixup_heap_objects_) {
- method->UpdateObjectsForImageRelocation(ForwardObjectAdapter(this));
+ method->UpdateObjectsForImageRelocation(ForwardObjectAdapter(this), pointer_size_);
}
- method->UpdateEntrypoints<kWithoutReadBarrier>(ForwardCodeAdapter(this));
+ method->UpdateEntrypoints<kWithoutReadBarrier>(ForwardCodeAdapter(this), pointer_size_);
}
private:
const bool fixup_heap_objects_;
+ const size_t pointer_size_;
};
class FixupArtFieldVisitor : public FixupVisitor, public ArtFieldVisitor {
@@ -912,6 +918,7 @@
uint32_t boot_image_end = 0;
uint32_t boot_oat_begin = 0;
uint32_t boot_oat_end = 0;
+ const size_t pointer_size = image_header.GetPointerSize();
gc::Heap* const heap = Runtime::Current()->GetHeap();
heap->GetBootImagesSize(&boot_image_begin, &boot_image_end, &boot_oat_begin, &boot_oat_end);
CHECK_NE(boot_image_begin, boot_image_end)
@@ -974,6 +981,7 @@
target_base,
image_header.GetImageSize()));
FixupObjectVisitor fixup_object_visitor(visited_bitmap.get(),
+ pointer_size,
boot_image,
boot_oat,
app_image,
@@ -1023,10 +1031,10 @@
dex_cache->SetResolvedMethods(new_methods);
}
for (size_t j = 0, num = dex_cache->NumResolvedMethods(); j != num; ++j) {
- ArtMethod* orig = mirror::DexCache::GetElementPtrSize(new_methods, j, sizeof(void*));
+ ArtMethod* orig = mirror::DexCache::GetElementPtrSize(new_methods, j, pointer_size);
ArtMethod* copy = fixup_adapter.ForwardObject(orig);
if (orig != copy) {
- mirror::DexCache::SetElementPtrSize(new_methods, j, copy, sizeof(void*));
+ mirror::DexCache::SetElementPtrSize(new_methods, j, copy, pointer_size);
}
}
}
@@ -1037,10 +1045,10 @@
dex_cache->SetResolvedFields(new_fields);
}
for (size_t j = 0, num = dex_cache->NumResolvedFields(); j != num; ++j) {
- ArtField* orig = mirror::DexCache::GetElementPtrSize(new_fields, j, sizeof(void*));
+ ArtField* orig = mirror::DexCache::GetElementPtrSize(new_fields, j, pointer_size);
ArtField* copy = fixup_adapter.ForwardObject(orig);
if (orig != copy) {
- mirror::DexCache::SetElementPtrSize(new_fields, j, copy, sizeof(void*));
+ mirror::DexCache::SetElementPtrSize(new_fields, j, copy, pointer_size);
}
}
}
@@ -1049,11 +1057,16 @@
{
// Only touches objects in the app image, no need for mutator lock.
TimingLogger::ScopedTiming timing("Fixup methods", &logger);
- FixupArtMethodVisitor method_visitor(fixup_image, boot_image, boot_oat, app_image, app_oat);
+ FixupArtMethodVisitor method_visitor(fixup_image,
+ pointer_size,
+ boot_image,
+ boot_oat,
+ app_image,
+ app_oat);
image_header.GetImageSection(ImageHeader::kSectionArtMethods).VisitPackedArtMethods(
&method_visitor,
target_base,
- sizeof(void*));
+ pointer_size);
}
if (fixup_image) {
{
@@ -1381,6 +1394,7 @@
image_header.GetOatDataBegin(),
image_header.GetOatFileBegin(),
!Runtime::Current()->IsAotCompiler(),
+ /*low_4gb*/false,
nullptr,
error_msg);
if (oat_file == nullptr) {
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 7155c79..033ea56 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -89,6 +89,7 @@
uint8_t* oat_file_begin,
bool writable,
bool executable,
+ bool low_4gb,
const char* abs_dex_location,
std::string* error_msg);
@@ -102,6 +103,7 @@
uint8_t* oat_file_begin,
bool writable,
bool executable,
+ bool low_4gb,
std::string* error_msg) = 0;
bool ComputeFields(uint8_t* requested_base,
@@ -133,6 +135,7 @@
uint8_t* oat_file_begin,
bool writable,
bool executable,
+ bool low_4gb,
const char* abs_dex_location,
std::string* error_msg) {
std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(location, executable));
@@ -140,6 +143,7 @@
oat_file_begin,
writable,
executable,
+ low_4gb,
error_msg)) {
return nullptr;
}
@@ -147,7 +151,6 @@
if (!ret->ComputeFields(requested_base, elf_filename, error_msg)) {
return nullptr;
}
-
ret->PreSetup(elf_filename);
if (!ret->Setup(abs_dex_location, error_msg)) {
@@ -532,6 +535,7 @@
uint8_t* oat_file_begin,
bool writable,
bool executable,
+ bool low_4gb,
std::string* error_msg) OVERRIDE;
// Ask the linker where it mmaped the file and notify our mmap wrapper of the regions.
@@ -558,6 +562,7 @@
uint8_t* oat_file_begin,
bool writable,
bool executable,
+ bool low_4gb,
std::string* error_msg) {
// Use dlopen only when flagged to do so, and when it's OK to load things executable.
// TODO: Also try when not executable? The issue here could be re-mapping as writable (as
@@ -567,6 +572,10 @@
*error_msg = "DlOpen is disabled.";
return false;
}
+ if (low_4gb) {
+ *error_msg = "DlOpen does not support low 4gb loading.";
+ return false;
+ }
if (writable) {
*error_msg = "DlOpen does not support writable loading.";
return false;
@@ -702,6 +711,7 @@
uint8_t* oat_file_begin, // Override base if not null
bool writable,
bool executable,
+ bool low_4gb,
const char* abs_dex_location,
std::string* error_msg);
@@ -723,6 +733,7 @@
uint8_t* oat_file_begin, // Override where the file is loaded to if not null
bool writable,
bool executable,
+ bool low_4gb,
std::string* error_msg) OVERRIDE;
void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) OVERRIDE {
@@ -733,6 +744,7 @@
uint8_t* oat_file_begin, // Override where the file is loaded to if not null
bool writable,
bool executable,
+ bool low_4gb,
std::string* error_msg);
private:
@@ -748,11 +760,17 @@
uint8_t* oat_file_begin, // Override base if not null
bool writable,
bool executable,
+ bool low_4gb,
const char* abs_dex_location,
std::string* error_msg) {
ScopedTrace trace("Open elf file " + location);
std::unique_ptr<ElfOatFile> oat_file(new ElfOatFile(location, executable));
- bool success = oat_file->ElfFileOpen(file, oat_file_begin, writable, executable, error_msg);
+ bool success = oat_file->ElfFileOpen(file,
+ oat_file_begin,
+ writable,
+ low_4gb,
+ executable,
+ error_msg);
if (!success) {
CHECK(!error_msg->empty());
return nullptr;
@@ -792,6 +810,7 @@
uint8_t* oat_file_begin, // Override where the file is loaded to if not null
bool writable,
bool executable,
+ bool low_4gb,
std::string* error_msg) {
ScopedTrace trace(__PRETTY_FUNCTION__);
std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
@@ -803,6 +822,7 @@
oat_file_begin,
writable,
executable,
+ low_4gb,
error_msg);
}
@@ -810,19 +830,21 @@
uint8_t* oat_file_begin,
bool writable,
bool executable,
+ bool low_4gb,
std::string* error_msg) {
ScopedTrace trace(__PRETTY_FUNCTION__);
// TODO: rename requested_base to oat_data_begin
elf_file_.reset(ElfFile::Open(file,
writable,
/*program_header_only*/true,
+ low_4gb,
error_msg,
oat_file_begin));
if (elf_file_ == nullptr) {
DCHECK(!error_msg->empty());
return false;
}
- bool loaded = elf_file_->Load(executable, error_msg);
+ bool loaded = elf_file_->Load(executable, low_4gb, error_msg);
DCHECK(loaded || !error_msg->empty());
return loaded;
}
@@ -870,6 +892,7 @@
uint8_t* requested_base,
uint8_t* oat_file_begin,
bool executable,
+ bool low_4gb,
const char* abs_dex_location,
std::string* error_msg) {
ScopedTrace trace("Open oat file " + location);
@@ -885,15 +908,15 @@
oat_file_begin,
false,
executable,
+ low_4gb,
abs_dex_location,
error_msg);
if (with_dlopen != nullptr) {
return with_dlopen;
}
if (kPrintDlOpenErrorMessage) {
- LOG(ERROR) << "Failed to dlopen: " << *error_msg;
+ LOG(ERROR) << "Failed to dlopen: " << filename << " with error " << *error_msg;
}
-
// 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.
@@ -913,6 +936,7 @@
oat_file_begin,
false,
executable,
+ low_4gb,
abs_dex_location,
error_msg);
return with_internal;
@@ -929,6 +953,7 @@
nullptr,
true,
false,
+ /*low_4gb*/false,
abs_dex_location,
error_msg);
}
@@ -944,6 +969,7 @@
nullptr,
false,
false,
+ /*low_4gb*/false,
abs_dex_location,
error_msg);
}
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 1084253..7af77ae 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -64,6 +64,7 @@
uint8_t* requested_base,
uint8_t* oat_file_begin,
bool executable,
+ bool low_4gb,
const char* abs_dex_location,
std::string* error_msg);
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 90712c6..cbc0ec6 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -815,8 +815,13 @@
const std::string& odex_file_name = *OdexFileName();
std::string error_msg;
cached_odex_file_.reset(OatFile::Open(odex_file_name.c_str(),
- odex_file_name.c_str(), nullptr, nullptr, load_executable_,
- dex_location_.c_str(), &error_msg));
+ odex_file_name.c_str(),
+ nullptr,
+ nullptr,
+ load_executable_,
+ /*low_4gb*/false,
+ dex_location_.c_str(),
+ &error_msg));
if (cached_odex_file_.get() == nullptr) {
VLOG(oat) << "OatFileAssistant test for existing pre-compiled oat file "
<< odex_file_name << ": " << error_msg;
@@ -846,8 +851,13 @@
const std::string& oat_file_name = *OatFileName();
std::string error_msg;
cached_oat_file_.reset(OatFile::Open(oat_file_name.c_str(),
- oat_file_name.c_str(), nullptr, nullptr, load_executable_,
- dex_location_.c_str(), &error_msg));
+ oat_file_name.c_str(),
+ nullptr,
+ nullptr,
+ load_executable_,
+ /*low_4gb*/false,
+ dex_location_.c_str(),
+ &error_msg));
if (cached_oat_file_.get() == nullptr) {
VLOG(oat) << "OatFileAssistant test for existing oat file "
<< oat_file_name << ": " << error_msg;
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index 4541468..046d8ae 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -218,9 +218,14 @@
// Verify the odex file was generated as expected and really is
// unrelocated.
- std::unique_ptr<OatFile> odex_file(OatFile::Open(
- odex_location.c_str(), odex_location.c_str(), nullptr, nullptr,
- false, dex_location.c_str(), &error_msg));
+ std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+ odex_location.c_str(),
+ nullptr,
+ nullptr,
+ false,
+ /*low_4gb*/false,
+ dex_location.c_str(),
+ &error_msg));
ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
const std::vector<gc::space::ImageSpace*> image_spaces =
@@ -252,9 +257,14 @@
setenv("ANDROID_DATA", android_data_.c_str(), 1);
// Verify the odex file was generated as expected.
- std::unique_ptr<OatFile> odex_file(OatFile::Open(
- odex_location.c_str(), odex_location.c_str(), nullptr, nullptr,
- false, dex_location.c_str(), &error_msg));
+ std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+ odex_location.c_str(),
+ nullptr,
+ nullptr,
+ false,
+ /*low_4gb*/false,
+ dex_location.c_str(),
+ &error_msg));
ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
EXPECT_TRUE(odex_file->IsPic());
}
@@ -269,9 +279,14 @@
ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
// Verify the odex file was generated as expected.
- std::unique_ptr<OatFile> odex_file(OatFile::Open(
- odex_location.c_str(), odex_location.c_str(), nullptr, nullptr,
- false, dex_location.c_str(), &error_msg));
+ std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+ odex_location.c_str(),
+ nullptr,
+ nullptr,
+ false,
+ /*low_4gb*/false,
+ dex_location.c_str(),
+ &error_msg));
ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
EXPECT_TRUE(odex_file->IsExtractOnly());
EXPECT_EQ(odex_file->GetOatHeader().GetImageFileLocationOatChecksum(), 0u);
@@ -290,9 +305,14 @@
ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
// Verify the odex file was generated as expected.
- std::unique_ptr<OatFile> odex_file(OatFile::Open(
- odex_location.c_str(), odex_location.c_str(), nullptr, nullptr,
- false, dex_location.c_str(), &error_msg));
+ std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+ odex_location.c_str(),
+ nullptr,
+ nullptr,
+ false,
+ /*low_4gb*/false,
+ dex_location.c_str(),
+ &error_msg));
printf("error %s", error_msg.c_str());
ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
EXPECT_TRUE(odex_file->IsProfileGuideCompiled());
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index e95f2c5..0dfb0cf 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -810,7 +810,11 @@
return false;
}
std::string error_msg;
- std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file.release(), false, false, &error_msg));
+ std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file.release(),
+ false,
+ false,
+ /*low_4gb*/false,
+ &error_msg));
if (elf_file.get() == nullptr) {
return false;
}