Throw IOException at source of failing to open a dex file.
Before is:
java.lang.ClassNotFoundException: Didn't find class "GCBench" on path: DexPathList[[zip file "/disk2/dalvik-dev/out/host/linux-x86/framework/GCBench.jar"],nativeLibraryDirectories=[/disk2/dalvik-dev/out/host/linux-x86/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
Suppressed: java.lang.ClassNotFoundException: GCBench
at java.lang.Class.classForName(Native Method)
at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
... 1 more
Caused by: java.lang.NoClassDefFoundError: Class "LGCBench;" not found
... 5 more
And after is:
java.lang.ClassNotFoundException: Didn't find class "GCBench" on path: DexPathList[[zip file "/disk2/dalvik-dev/out/host/linux-x86/framework/GCBench.jar"],nativeLibraryDirectories=[/disk2/dalvik-dev/out/host/linux-x86/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
Suppressed: java.io.IOException: Zip archive '/disk2/dalvik-dev/out/host/linux-x86/framework/GCBench.jar' doesn't contain classes.dex
at dalvik.system.DexFile.openDexFile(Native Method)
at dalvik.system.DexFile.<init>(DexFile.java:80)
at dalvik.system.DexFile.<init>(DexFile.java:59)
at dalvik.system.DexPathList.loadDexFile(DexPathList.java:268)
at dalvik.system.DexPathList.makeDexElements(DexPathList.java:235)
at dalvik.system.DexPathList.<init>(DexPathList.java:113)
at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:48)
at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:38)
at java.lang.ClassLoader.createSystemClassLoader(ClassLoader.java:128)
at java.lang.ClassLoader.access$000(ClassLoader.java:65)
at java.lang.ClassLoader$SystemClassLoader.<clinit>(ClassLoader.java:81)
at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:137)
Suppressed: java.lang.ClassNotFoundException: GCBench
at java.lang.Class.classForName(Native Method)
at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
... 1 more
Caused by: java.lang.NoClassDefFoundError: Class "LGCBench;" not found
... 5 more
Also, move dex file verifier messages out of logs.
In the process the ClassLinker::dex_lock_ needed tidying to cover a smaller
scope. Bug 11301553.
Change-Id: I80058652e11e7ea63457cc01a0cb48afe1c15543
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 7ecaf01..7553dcc 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -48,19 +48,21 @@
}
OatFile* OatFile::OpenMemory(std::vector<uint8_t>& oat_contents,
- const std::string& location) {
+ const std::string& location,
+ std::string* error_msg) {
CHECK(!oat_contents.empty()) << location;
CheckLocation(location);
UniquePtr<OatFile> oat_file(new OatFile(location));
oat_file->begin_ = &oat_contents[0];
oat_file->end_ = &oat_contents[oat_contents.size()];
- return oat_file->Setup() ? oat_file.release() : NULL;
+ return oat_file->Setup(error_msg) ? oat_file.release() : nullptr;
}
OatFile* OatFile::Open(const std::string& filename,
const std::string& location,
byte* requested_base,
- bool executable) {
+ bool executable,
+ std::string* error_msg) {
CHECK(!filename.empty()) << location;
CheckLocation(filename);
#ifdef ART_USE_PORTABLE_COMPILER
@@ -70,7 +72,7 @@
// open a generated dex file by name, remove the file, then open
// another generated dex file with the same name. http://b/10614658
if (executable) {
- return OpenDlopen(filename, location, requested_base);
+ return OpenDlopen(filename, location, requested_base, error_msg);
}
#endif
// If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
@@ -83,21 +85,22 @@
if (file.get() == NULL) {
return NULL;
}
- return OpenElfFile(file.get(), location, requested_base, false, executable);
+ return OpenElfFile(file.get(), location, requested_base, false, executable, error_msg);
}
-OatFile* OatFile::OpenWritable(File* file, const std::string& location) {
+OatFile* OatFile::OpenWritable(File* file, const std::string& location, std::string* error_msg) {
CheckLocation(location);
- return OpenElfFile(file, location, NULL, true, false);
+ return OpenElfFile(file, location, NULL, true, false, error_msg);
}
OatFile* OatFile::OpenDlopen(const std::string& elf_filename,
const std::string& location,
- byte* requested_base) {
+ byte* requested_base,
+ std::string* error_msg) {
UniquePtr<OatFile> oat_file(new OatFile(location));
- bool success = oat_file->Dlopen(elf_filename, requested_base);
+ bool success = oat_file->Dlopen(elf_filename, requested_base, error_msg);
if (!success) {
- return NULL;
+ return nullptr;
}
return oat_file.release();
}
@@ -106,11 +109,13 @@
const std::string& location,
byte* requested_base,
bool writable,
- bool executable) {
+ bool executable,
+ std::string* error_msg) {
UniquePtr<OatFile> oat_file(new OatFile(location));
- bool success = oat_file->ElfFileOpen(file, requested_base, writable, executable);
+ bool success = oat_file->ElfFileOpen(file, requested_base, writable, executable, error_msg);
if (!success) {
- return NULL;
+ CHECK(!error_msg->empty());
+ return nullptr;
}
return oat_file.release();
}
@@ -127,120 +132,117 @@
}
}
-bool OatFile::Dlopen(const std::string& elf_filename, byte* requested_base) {
+bool OatFile::Dlopen(const std::string& elf_filename, byte* requested_base,
+ std::string* error_msg) {
char* absolute_path = realpath(elf_filename.c_str(), NULL);
if (absolute_path == NULL) {
- VLOG(class_linker) << "Failed to find absolute path for " << elf_filename;
+ *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str());
return false;
}
dlopen_handle_ = dlopen(absolute_path, RTLD_NOW);
free(absolute_path);
if (dlopen_handle_ == NULL) {
- VLOG(class_linker) << "Failed to dlopen " << elf_filename << ": " << dlerror();
+ *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror());
return false;
}
begin_ = reinterpret_cast<byte*>(dlsym(dlopen_handle_, "oatdata"));
if (begin_ == NULL) {
- LOG(WARNING) << "Failed to find oatdata symbol in " << elf_filename << ": " << dlerror();
+ *error_msg = StringPrintf("Failed to find oatdata symbol in '%s': %s", elf_filename.c_str(),
+ dlerror());
return false;
}
if (requested_base != NULL && begin_ != requested_base) {
- std::string maps;
- ReadFileToString("/proc/self/maps", &maps);
- LOG(WARNING) << "Failed to find oatdata symbol at expected address: oatdata="
- << reinterpret_cast<const void*>(begin_) << " != expected="
- << reinterpret_cast<const void*>(requested_base)
- << " /proc/self/maps:\n" << maps;
+ *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: "
+ "oatdata=%p != expected=%p /proc/self/maps:\n",
+ begin_, requested_base);
+ ReadFileToString("/proc/self/maps", error_msg);
return false;
}
end_ = reinterpret_cast<byte*>(dlsym(dlopen_handle_, "oatlastword"));
if (end_ == NULL) {
- LOG(WARNING) << "Failed to find oatlastword symbol in " << elf_filename << ": " << dlerror();
+ *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s': %s", elf_filename.c_str(),
+ dlerror());
return false;
}
// Readjust to be non-inclusive upper bound.
end_ += sizeof(uint32_t);
- return Setup();
+ return Setup(error_msg);
}
-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) {
- if (writable) {
- PLOG(WARNING) << "Failed to open ELF file for " << file->GetPath();
- }
+bool OatFile::ElfFileOpen(File* file, byte* requested_base, bool writable, bool executable,
+ std::string* error_msg) {
+ elf_file_.reset(ElfFile::Open(file, writable, true, error_msg));
+ if (elf_file_.get() == nullptr) {
+ DCHECK(!error_msg->empty());
return false;
}
- bool loaded = elf_file_->Load(executable);
+ bool loaded = elf_file_->Load(executable, error_msg);
if (!loaded) {
- LOG(WARNING) << "Failed to load ELF file " << file->GetPath();
+ DCHECK(!error_msg->empty());
return false;
}
begin_ = elf_file_->FindDynamicSymbolAddress("oatdata");
if (begin_ == NULL) {
- LOG(WARNING) << "Failed to find oatdata symbol in " << file->GetPath();
+ *error_msg = StringPrintf("Failed to find oatdata symbol in '%s'", file->GetPath().c_str());
return false;
}
if (requested_base != NULL && begin_ != requested_base) {
- std::string maps;
- ReadFileToString("/proc/self/maps", &maps);
- LOG(WARNING) << "Failed to find oatdata symbol at expected address: oatdata="
- << reinterpret_cast<const void*>(begin_) << " != expected="
- << reinterpret_cast<const void*>(requested_base)
- << " /proc/self/maps:\n" << maps;
+ *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: "
+ "oatdata=%p != expected=%p /proc/self/maps:\n",
+ begin_, requested_base);
+ ReadFileToString("/proc/self/maps", error_msg);
return false;
}
end_ = elf_file_->FindDynamicSymbolAddress("oatlastword");
if (end_ == NULL) {
- LOG(WARNING) << "Failed to find oatlastword symbol in " << file->GetPath();
+ *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s'", file->GetPath().c_str());
return false;
}
// Readjust to be non-inclusive upper bound.
end_ += sizeof(uint32_t);
- return Setup();
+ return Setup(error_msg);
}
-bool OatFile::Setup() {
+bool OatFile::Setup(std::string* error_msg) {
if (!GetOatHeader().IsValid()) {
- LOG(WARNING) << "Invalid oat magic for " << GetLocation();
+ *error_msg = StringPrintf("Invalid oat magic for '%s'", GetLocation().c_str());
return false;
}
const byte* oat = Begin();
oat += sizeof(OatHeader);
if (oat > End()) {
- LOG(ERROR) << "In oat file " << GetLocation() << " found truncated OatHeader";
+ *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader", GetLocation().c_str());
return false;
}
oat += GetOatHeader().GetImageFileLocationSize();
if (oat > End()) {
- LOG(ERROR) << "In oat file " << GetLocation() << " found truncated image file location: "
- << reinterpret_cast<const void*>(Begin())
- << "+" << sizeof(OatHeader)
- << "+" << GetOatHeader().GetImageFileLocationSize()
- << "<=" << reinterpret_cast<const void*>(End());
+ *error_msg = StringPrintf("In oat file '%s' found truncated image file location: "
+ "%p + %zd + %ud <= %p", GetLocation().c_str(),
+ Begin(), sizeof(OatHeader), GetOatHeader().GetImageFileLocationSize(),
+ End());
return false;
}
for (size_t i = 0; i < GetOatHeader().GetDexFileCount(); i++) {
size_t dex_file_location_size = *reinterpret_cast<const uint32_t*>(oat);
- if (dex_file_location_size == 0U) {
- LOG(ERROR) << "In oat file " << GetLocation() << " found OatDexFile # " << i
- << " with empty location name";
+ if (UNLIKELY(dex_file_location_size == 0U)) {
+ *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd with empty location name",
+ GetLocation().c_str(), i);
return false;
}
oat += sizeof(dex_file_location_size);
- if (oat > End()) {
- LOG(ERROR) << "In oat file " << GetLocation() << " found OatDexFile # " << i
- << " truncated after dex file location size";
+ if (UNLIKELY(oat > End())) {
+ *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd truncated after dex file "
+ "location size", GetLocation().c_str(), i);
return false;
}
const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
oat += dex_file_location_size;
- if (oat > End()) {
- LOG(ERROR) << "In oat file " << GetLocation() << " found OatDexFile # " << i
- << " with truncated dex file location";
+ if (UNLIKELY(oat > End())) {
+ *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd with truncated dex file "
+ "location", GetLocation().c_str(), i);
return false;
}
@@ -248,55 +250,54 @@
uint32_t dex_file_checksum = *reinterpret_cast<const uint32_t*>(oat);
oat += sizeof(dex_file_checksum);
- if (oat > End()) {
- LOG(ERROR) << "In oat file " << GetLocation() << " found OatDexFile # " << i
- << " for "<< dex_file_location
- << " truncated after dex file checksum";
+ if (UNLIKELY(oat > End())) {
+ *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated after "
+ "dex file checksum", GetLocation().c_str(), i,
+ dex_file_location.c_str());
return false;
}
uint32_t dex_file_offset = *reinterpret_cast<const uint32_t*>(oat);
- if (dex_file_offset == 0U) {
- LOG(ERROR) << "In oat file " << GetLocation() << " found OatDexFile # " << i
- << " for "<< dex_file_location
- << " with zero dex file offset";
+ if (UNLIKELY(dex_file_offset == 0U)) {
+ *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with zero dex "
+ "file offset", GetLocation().c_str(), i, dex_file_location.c_str());
return false;
}
- if (dex_file_offset > Size()) {
- LOG(ERROR) << "In oat file " << GetLocation() << " found OatDexFile # " << i
- << " for "<< dex_file_location
- << " with dex file offset" << dex_file_offset << " > " << Size();
+ if (UNLIKELY(dex_file_offset > Size())) {
+ *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with dex file "
+ "offset %ud > %zd", GetLocation().c_str(), i,
+ dex_file_location.c_str(), dex_file_offset, Size());
return false;
}
oat += sizeof(dex_file_offset);
- if (oat > End()) {
- LOG(ERROR) << "In oat file " << GetLocation() << " found OatDexFile # " << i
- << " for "<< dex_file_location
- << " truncated after dex file offset";
+ if (UNLIKELY(oat > End())) {
+ *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
+ " after dex file offsets", GetLocation().c_str(), i,
+ dex_file_location.c_str());
return false;
}
const uint8_t* dex_file_pointer = Begin() + dex_file_offset;
- if (!DexFile::IsMagicValid(dex_file_pointer)) {
- LOG(ERROR) << "In oat file " << GetLocation() << " found OatDexFile # " << i
- << " for "<< dex_file_location
- << " with invalid dex file magic: " << dex_file_pointer;
+ if (UNLIKELY(!DexFile::IsMagicValid(dex_file_pointer))) {
+ *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with invalid "
+ " dex file magic '%s'", GetLocation().c_str(), i,
+ dex_file_location.c_str(), dex_file_pointer);
return false;
}
- if (!DexFile::IsVersionValid(dex_file_pointer)) {
- LOG(ERROR) << "In oat file " << GetLocation() << " found OatDexFile # " << i
- << " for "<< dex_file_location
- << " with invalid dex file version: " << dex_file_pointer;
+ if (UNLIKELY(!DexFile::IsVersionValid(dex_file_pointer))) {
+ *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with invalid "
+ " dex file version '%s'", GetLocation().c_str(), i,
+ dex_file_location.c_str(), dex_file_pointer);
return false;
}
const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
const uint32_t* methods_offsets_pointer = reinterpret_cast<const uint32_t*>(oat);
oat += (sizeof(*methods_offsets_pointer) * header->class_defs_size_);
- if (oat > End()) {
- LOG(ERROR) << "In oat file " << GetLocation() << " found OatDexFile # " << i
- << " for "<< dex_file_location
- << " with truncated method offsets";
+ if (UNLIKELY(oat > End())) {
+ *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with truncated "
+ " method offsets", GetLocation().c_str(), i,
+ dex_file_location.c_str());
return false;
}
@@ -323,8 +324,8 @@
return end_;
}
-const OatFile::OatDexFile* OatFile::GetOatDexFile(const std::string& dex_location,
- const uint32_t* const dex_location_checksum,
+const OatFile::OatDexFile* OatFile::GetOatDexFile(const char* dex_location,
+ const uint32_t* dex_location_checksum,
bool warn_if_not_found) const {
Table::const_iterator it = oat_dex_files_.find(dex_location);
if (it != oat_dex_files_.end()) {
@@ -373,9 +374,9 @@
return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_;
}
-const DexFile* OatFile::OatDexFile::OpenDexFile() const {
+const DexFile* OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const {
return DexFile::Open(dex_file_pointer_, FileSize(), dex_file_location_,
- dex_file_location_checksum_);
+ dex_file_location_checksum_, error_msg);
}
const OatFile::OatClass* OatFile::OatDexFile::GetOatClass(uint16_t class_def_index) const {