Skip to content
This repository was archived by the owner on Jun 1, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion build/Android.common_build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,6 @@ art_cflags := \
-Wunreachable-code \
-Wredundant-decls \
-Wshadow \
-Wunused \
-fvisibility=protected \
$(art_default_gc_type_cflags)

Expand Down
2 changes: 2 additions & 0 deletions build/Android.executable.mk
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ define build-art-executable
art_target_or_host := $(5)
art_ndebug_or_debug := $(6)
art_multilib := $(7)
art_static_libraries := $(8)
art_out_binary_name :=

include $(CLEAR_VARS)
Expand All @@ -55,6 +56,7 @@ define build-art-executable
LOCAL_SRC_FILES := $$(art_source)
LOCAL_C_INCLUDES += $(ART_C_INCLUDES) art/runtime art/cmdline $$(art_c_includes)
LOCAL_SHARED_LIBRARIES += $$(art_shared_libraries)
LOCAL_STATIC_LIBRARIES += $$(art_static_libraries)
LOCAL_WHOLE_STATIC_LIBRARIES += libsigchain

ifeq ($$(art_ndebug_or_debug),ndebug)
Expand Down
8 changes: 4 additions & 4 deletions dex2oat/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,16 @@ else
endif

ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
$(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libart-compiler,art/compiler,target,ndebug,$(dex2oat_target_arch)))
$(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libart-compiler,art/compiler,target,ndebug,$(dex2oat_target_arch),libxz))
endif
ifeq ($(ART_BUILD_TARGET_DEBUG),true)
$(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libartd-compiler,art/compiler,target,debug,$(dex2oat_target_arch)))
$(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libartd-compiler,art/compiler,target,debug,$(dex2oat_target_arch),libxz))
endif

# We always build dex2oat and dependencies, even if the host build is otherwise disabled, since they are used to cross compile for the target.
ifeq ($(ART_BUILD_HOST_NDEBUG),true)
$(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libart-compiler libziparchive-host,art/compiler,host,ndebug,$(dex2oat_host_arch)))
$(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libart-compiler libziparchive-host,art/compiler,host,ndebug,$(dex2oat_host_arch),libxz_host))
endif
ifeq ($(ART_BUILD_HOST_DEBUG),true)
$(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libartd-compiler libziparchive-host,art/compiler,host,debug,$(dex2oat_host_arch)))
$(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libartd-compiler libziparchive-host,art/compiler,host,debug,$(dex2oat_host_arch),libxz_host))
endif
151 changes: 148 additions & 3 deletions dex2oat/dex2oat.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@
#ifdef HAVE_ANDROID_OS
#include "cutils/properties.h"
#endif
#include "xz_config.h"
#include "xz.h"
#include "xz_private.h"

namespace art {

Expand Down Expand Up @@ -1325,7 +1328,7 @@ class Dex2Oat FINAL {
}
ATRACE_END();
} else {
size_t failure_count = OpenDexFiles(dex_filenames_, dex_locations_, &opened_dex_files_);
size_t failure_count = OpenDexFiles(dex_filenames_, dex_locations_, &opened_dex_files_, swap_fd_);
if (failure_count > 0) {
LOG(ERROR) << "Failed to open some dex files: " << failure_count;
return false;
Expand Down Expand Up @@ -1673,9 +1676,116 @@ class Dex2Oat FINAL {
}

private:
static File* InflateXZ(const std::string& filename, int out_fd, std::string* err) {
if (out_fd == -1) {
*err = "No swap file available";
return nullptr;
}

struct xz_buf b;
struct xz_dec *dec;
uint8_t xz_out[BUFSIZ];
enum xz_ret ret;
std::string uncompressed;

std::ifstream t(filename.c_str());
std::ostringstream in_contents;
in_contents << t.rdbuf();
std::string input_str = in_contents.str();

b.in = (const uint8_t*) input_str.c_str();
b.in_pos = 0;
b.in_size = input_str.length();
b.out = xz_out;
b.out_pos = 0;
b.out_size = BUFSIZ;

xz_crc32_init();

xz_crc64_init();

dec = xz_dec_init(XZ_DYNALLOC, 1 << 26);
if(dec == NULL) {
LOG(WARNING) << "xz_dec_init FAILED!";
return nullptr;
}

while (b.in_pos != b.in_size) {
ret = xz_dec_run(dec, &b);
uncompressed.append((const char*) xz_out, b.out_pos);
b.out_pos = 0;

if (ret == XZ_OK)
continue;

if (ret == XZ_STREAM_END) {

xz_dec_end(dec);

std::unique_ptr<File> out_file_ptr(new File(out_fd, false));

if (!out_file_ptr->WriteFully(uncompressed.c_str(), uncompressed.length())) {
*err = StringPrintf("Could not write to fd=%d", out_fd);
return nullptr;
}

if (out_file_ptr->Flush() != 0) {
*err = StringPrintf("Could not flush swap file fd=%d", out_fd);
return nullptr;
}

out_file_ptr->DisableAutoClose();
return out_file_ptr.release();
}

if (ret == XZ_UNSUPPORTED_CHECK) {
LOG(WARNING) << "Unsupported check; not verifying file integrity";
continue;
}

if (ret == XZ_MEM_ERROR) {
LOG(ERROR) << "Memory allocation failed";
break;
}

if (ret == XZ_MEMLIMIT_ERROR) {
LOG(ERROR) << "Memory usage limit reached";
break;
}

if (ret == XZ_FORMAT_ERROR) {
LOG(ERROR) << "XZ file format error";
break;
}

if (ret == XZ_OPTIONS_ERROR) {
LOG(ERROR) << "Unsupported options in the .xz headers";
break;
}

if (ret == XZ_DATA_ERROR) {
LOG(ERROR) << "File data corrupt";
break;
}

if (ret == XZ_BUF_ERROR) {
LOG(ERROR) << "File buffer corrupt";
break;
} else {
LOG(ERROR) << "XZ Bug!";
break;
}
}

*err = StringPrintf("Could not uncompress file=%s", filename.c_str());
xz_dec_end(dec);
return nullptr;
}

static size_t OpenDexFiles(const std::vector<const char*>& dex_filenames,
const std::vector<const char*>& dex_locations,
std::vector<std::unique_ptr<const DexFile>>* dex_files) {
std::vector<std::unique_ptr<const DexFile>>* dex_files,
int& swap_fd) {
DCHECK(dex_files != nullptr) << "OpenDexFiles out-param is nullptr";
size_t failure_count = 0;
for (size_t i = 0; i < dex_filenames.size(); i++) {
Expand All @@ -1687,7 +1797,42 @@ class Dex2Oat FINAL {
LOG(WARNING) << "Skipping non-existent dex file '" << dex_filename << "'";
continue;
}
if (!DexFile::Open(dex_filename, dex_location, &error_msg, dex_files)) {
std::unique_ptr<File> file;
if (EndsWith(dex_filename, ".xz")) {
file.reset(InflateXZ(dex_filename, swap_fd, &error_msg));
if (file.get() == nullptr) {
LOG(WARNING) << "Failed to inflate " << dex_filename << "': " << error_msg;
++failure_count;
continue;
}
swap_fd = -1;
}
if (file.get() != nullptr) {
std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file.release(), PROT_READ | PROT_WRITE, MAP_PRIVATE, &error_msg));
if (elf_file.get() == nullptr) {
LOG(WARNING) << "Failed to open ELF file from '" << dex_filename << "': " << error_msg;
++failure_count;
continue;
}
const OatFile* oat_file = OatFile::OpenWithElfFile(elf_file.release(), dex_filename, nullptr, &error_msg);
if (oat_file == nullptr) {
LOG(WARNING) << "Failed to open oat file from '" << dex_filename << "': " << error_msg;
++failure_count;
continue;
} else {
for (const OatFile::OatDexFile* oat_dex_file : oat_file->GetOatDexFiles()) {
CHECK(oat_dex_file != nullptr);
std::unique_ptr<const DexFile> dex_file(oat_dex_file->OpenDexFile(&error_msg));
if (dex_file.get() != nullptr) {
dex_files->push_back(std::move(dex_file));
} else {
LOG(WARNING) << "Failed to open dex file '" << oat_dex_file->GetDexFileLocation()
<< "' from file '" << dex_filename << "': " << error_msg;
++failure_count;
}
}
}
} else if (!DexFile::Open(dex_filename, dex_location, &error_msg, dex_files)) {
LOG(WARNING) << "Failed to open .dex from file '" << dex_filename << "': " << error_msg;
++failure_count;
}
Expand Down
1 change: 1 addition & 0 deletions runtime/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ LIBART_COMMON_SRC_FILES := \
native/libcore_util_CharsetUtils.cc \
native/org_apache_harmony_dalvik_ddmc_DdmServer.cc \
native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc \
native/samsung.cc \
native/sun_misc_Unsafe.cc \
oat.cc \
oat_file.cc \
Expand Down
50 changes: 49 additions & 1 deletion runtime/class_linker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,39 @@ ClassLinker::ClassLinker(InternTable* intern_table)
std::fill_n(find_array_class_cache_, kFindArrayCacheSize, GcRoot<mirror::Class>(nullptr));
}

static void dexCacheExtraFieldsWorkaround(const DexFile* dex_file) {
const char* descriptor = "Ljava/lang/DexCache;";
const size_t hash = ComputeModifiedUtf8Hash(descriptor);
const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor, hash);
if (dex_class_def != nullptr) {
const uint8_t* class_data = dex_file->GetClassData(*dex_class_def);
if (class_data != nullptr) {
for (ClassDataItemIterator it(*dex_file, class_data); it.HasNextInstanceField(); it.Next()) {
const DexFile::FieldId& field_id = dex_file->GetFieldId(it.GetMemberIndex());
const char* name = dex_file->GetFieldName(field_id);
// Additional fields are normally 'literals' and 'z_padding'.
// Some devices have only 'literals' (without 'z_padding') but they work the same.
if (strcmp(name, "literals") == 0) {
mirror::sDexCacheJavaClassHasExtraFields = true;
LOG(INFO) << "java.lang.DexCache compatibility mode";
break;
}
}
}
}
}

static void checkOatFileDexCacheExtraFields(OatFile& oat_file) {
// Workaround for DexCache extra fields
std::string core_libart_jar = GetAndroidRoot();
core_libart_jar += "/framework/core-libart.jar";
const OatFile::OatDexFile* oat_dex_file = oat_file.GetOatDexFile(core_libart_jar.c_str(), nullptr);
std::string error_msg;
std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
dexCacheExtraFieldsWorkaround(dex_file.get());
dex_file.reset();
}

void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> boot_class_path) {
VLOG(startup) << "ClassLinker::Init";

Expand Down Expand Up @@ -409,6 +442,18 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b

// now that these are registered, we can use AllocClass() and AllocObjectArray

CHECK_NE(0U, boot_class_path.size());
std::string core_libart_jar = GetAndroidRoot();
core_libart_jar += "/framework/core-libart.jar";
for (auto& dex_file : boot_class_path) {
CHECK(dex_file.get() != nullptr);
// Workaround for DexCache extra fields. and String extra method
if (dex_file->GetLocation() == core_libart_jar.c_str()) {
dexCacheExtraFieldsWorkaround(dex_file.get());
break;
}
}

// Set up DexCache. This cannot be done later since AppendToBootClassPath calls AllocDexCache.
Handle<mirror::Class> java_lang_DexCache(hs.NewHandle(
AllocClass(self, java_lang_Class.Get(), mirror::DexCache::ClassSize(image_pointer_size_))));
Expand All @@ -431,9 +476,9 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
// Setup boot_class_path_ and register class_path now that we can use AllocObjectArray to create
// DexCache instances. Needs to be after String, Field, Method arrays since AllocDexCache uses
// these roots.
CHECK_NE(0U, boot_class_path.size());
for (auto& dex_file : boot_class_path) {
CHECK(dex_file.get() != nullptr);

AppendToBootClassPath(self, *dex_file);
opened_dex_files_.push_back(std::move(dex_file));
}
Expand Down Expand Up @@ -1134,6 +1179,9 @@ void ClassLinker::InitFromImage() {

CHECK_EQ(oat_file.GetOatHeader().GetDexFileCount(),
static_cast<uint32_t>(dex_caches->GetLength()));

checkOatFileDexCacheExtraFields(oat_file);

for (int32_t i = 0; i < dex_caches->GetLength(); i++) {
StackHandleScope<1> hs2(self);
Handle<mirror::DexCache> dex_cache(hs2.NewHandle(dex_caches->Get(i)));
Expand Down
6 changes: 6 additions & 0 deletions runtime/jni_internal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2170,6 +2170,12 @@ class JNI {
}

if (m == nullptr) {
if (PrettyDescriptor(c) == "dalvik.system.PathClassLoader" && strcmp(name, "openNative") == 0) {
LOG(WARNING) << "Native method " << PrettyDescriptor(c) << "." << name << sig
<< " not found in " << c->GetDexCache()->GetLocation()->ToModifiedUtf8();
continue;
}

LOG(return_errors ? ERROR : INTERNAL_FATAL) << "Failed to register native method "
<< PrettyDescriptor(c) << "." << name << sig << " in "
<< c->GetDexCache()->GetLocation()->ToModifiedUtf8();
Expand Down
6 changes: 4 additions & 2 deletions runtime/mirror/dex_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
namespace art {
namespace mirror {

bool sDexCacheJavaClassHasExtraFields = false;

void DexCache::Init(const DexFile* dex_file, String* location, ObjectArray<String>* strings,
ObjectArray<Class>* resolved_types, PointerArray* resolved_methods,
PointerArray* resolved_fields, size_t pointer_size) {
Expand All @@ -42,10 +44,10 @@ void DexCache::Init(const DexFile* dex_file, String* location, ObjectArray<Strin
CHECK(resolved_fields != nullptr);

SetDexFile(dex_file);
SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location);
SetFieldObject<false>(LocationOffset(), location);
SetFieldObject<false>(StringsOffset(), strings);
SetFieldObject<false>(ResolvedFieldsOffset(), resolved_fields);
SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_), resolved_types);
SetFieldObject<false>(ResolvedTypesOffset(), resolved_types);
SetFieldObject<false>(ResolvedMethodsOffset(), resolved_methods);

Runtime* const runtime = Runtime::Current();
Expand Down
Loading