oatdump
FROM MAKE:
mm dump-boot-oat
ON HOST:
oatdump --dex-file=$ANDROID_PRODUCT_OUT/system/framework/core.jar --image=$ANDROID_PRODUCT_OUT/system/framework/boot.oat --strip-prefix=$ANDROID_PRODUCT_OUT
oatdump --boot-dex-file=$ANDROID_PRODUCT_OUT/system/framework/core.jar --boot=$ANDROID_PRODUCT_OUT/system/framework/boot.oat --dex-file=$ANDROID_PRODUCT_OUT/system/framework/art-test-dex-HelloWorld.jar --image=$ANDROID_PRODUCT_OUT//system/framework/art-test-dex-HelloWorld.oat --strip-prefix=$ANDROID_PRODUCT_OUT
ON TARGET:
adb shell oatdump --dex-file=/system/framework/core.jar --image=/system/framework/boot.oat
adb shell oatdumpd --boot-dex-file=/system/framework/core.jar --boot=/system/framework/boot.oat --dex-file=/system/framework/art-test-dex-HelloWorld.jar --image=/system/framework/art-test-dex-HelloWorld.oat
Change-Id: Iad2ae40a9cf2dc28799ff5dc5222d50f1bc6b39f
diff --git a/Android.mk b/Android.mk
index ef8eb75..abdcc06 100644
--- a/Android.mk
+++ b/Android.mk
@@ -110,6 +110,10 @@
(adb pull /sdcard/test-art-target-oat-Fibonacci /tmp/ && echo test-art-target-oat-Fibonacci PASSED) || (echo test-art-target-oat-Fibonacci FAILED && exit 1)
$(hide) rm /tmp/test-art-target-oat-Fibonacci
+.PHONY: dump-boot-oat
+dump-boot-oat: $(TARGET_BOOT_OAT) $(OATDUMP)
+ $(OATDUMP) $(addprefix --dex-file=,$(TARGET_BOOT_DEX)) --image=$(TARGET_BOOT_OAT) --strip-prefix=$(PRODUCT_OUT)
+
# "mm cpplint-art" to style check art source files
.PHONY: cpplint-art
cpplint-art:
diff --git a/build/Android.common.mk b/build/Android.common.mk
index c22deed..1ab48f6 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -53,6 +53,9 @@
DEX2OAT_SRC_FILES := \
src/dex2oat.cc
+OATDUMP_SRC_FILES := \
+ src/oatdump.cc
+
OATEXEC_SRC_FILES := \
src/oatexec.cc
diff --git a/build/Android.executable.mk b/build/Android.executable.mk
index 60d37ee..ff6ad17 100644
--- a/build/Android.executable.mk
+++ b/build/Android.executable.mk
@@ -71,18 +71,22 @@
ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
$(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),target,ndebug))
+ $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),target,ndebug))
$(eval $(call build-art-executable,oatexec,$(OATEXEC_SRC_FILES),target,ndebug))
endif
ifeq ($(ART_BUILD_TARGET_DEBUG),true)
$(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),target,debug))
+ $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),target,debug))
$(eval $(call build-art-executable,oatexec,$(OATEXEC_SRC_FILES),target,debug))
endif
ifeq ($(ART_BUILD_HOST_NDEBUG),true)
$(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),host,ndebug))
+ $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),host,ndebug))
$(eval $(call build-art-executable,oatexec,$(OATEXEC_SRC_FILES),host,ndebug))
endif
ifeq ($(ART_BUILD_HOST_DEBUG),true)
$(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),host,debug))
+ $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),host,debug))
$(eval $(call build-art-executable,oatexec,$(OATEXEC_SRC_FILES),host,debug))
endif
diff --git a/build/Android.oat.mk b/build/Android.oat.mk
index 86be8b6..e027911 100644
--- a/build/Android.oat.mk
+++ b/build/Android.oat.mk
@@ -19,6 +19,11 @@
# TODO: for now, override with debug version for better error reporting
DEX2OAT := $(DEX2OATD)
+OATDUMP := $(HOST_OUT_EXECUTABLES)/oatdump$(HOST_EXECUTABLE_SUFFIX)
+OATDUMPD := $(HOST_OUT_EXECUTABLES)/oatdumpd$(HOST_EXECUTABLE_SUFFIX)
+# TODO: for now, override with debug version for better error reporting
+OATDUMP := $(OATDUMPD)
+
# start of oat reserved address space
OAT_HOST_BASE_ADDRESS := 0x50000000
OAT_TARGET_BASE_ADDRESS := 0x50000000
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 037887d..232390a 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -438,7 +438,7 @@
FinishInit();
}
-void ClassLinker::InitFromImageCallback(Object* obj, void *arg) {
+void ClassLinker::InitFromImageCallback(Object* obj, void* arg) {
DCHECK(obj != NULL);
DCHECK(arg != NULL);
InitFromImageCallbackState* state = reinterpret_cast<InitFromImageCallbackState*>(arg);
diff --git a/src/class_linker.h b/src/class_linker.h
index 108059c..53291b5 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -167,7 +167,7 @@
// Initialize class linker from pre-initialized image.
void InitFromImage(const std::vector<const DexFile*>& boot_class_path_,
const std::vector<const DexFile*>& class_path_);
- static void InitFromImageCallback(Object* obj, void *arg);
+ static void InitFromImageCallback(Object* obj, void* arg);
struct InitFromImageCallbackState;
void FinishInit();
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index 304c7d2..f60699c 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -20,8 +20,8 @@
"Usage: dex2oat [options]...\n"
"\n");
fprintf(stderr,
- " --dex-file=<dex-file>: specifies a .dex files to compile. At least one .dex\n"
- " but more than one may be included. \n"
+ " --dex-file=<dex-file>: specifies a .dex file to compile. At least one .dex\n"
+ " file must be specified. \n"
" Example: --dex-file=/system/framework/core.jar\n"
"\n");
fprintf(stderr,
@@ -54,20 +54,6 @@
exit(EXIT_FAILURE);
}
-static void OpenDexFiles(std::vector<const char*>& dex_filenames,
- std::vector<const DexFile*>& dex_files,
- const std::string& strip_location_prefix) {
- for (size_t i = 0; i < dex_filenames.size(); i++) {
- const char* dex_filename = dex_filenames[i];
- const DexFile* dex_file = DexFile::Open(dex_filename, strip_location_prefix);
- if (dex_file == NULL) {
- fprintf(stderr, "could not open .dex from file %s\n", dex_filename);
- exit(EXIT_FAILURE);
- }
- dex_files.push_back(dex_file);
- }
-}
-
int dex2oat(int argc, char** argv) {
// Skip over argv[0].
argv++;
@@ -122,6 +108,11 @@
return EXIT_FAILURE;
}
+ if (dex_filenames.empty()) {
+ fprintf(stderr, "no --dex-file values specified\n");
+ return EXIT_FAILURE;
+ }
+
if (boot_image_option.empty()) {
if (image_base == 0) {
fprintf(stderr, "non-zero --base not specified\n");
@@ -129,16 +120,16 @@
}
} else {
if (boot_dex_filenames.empty()) {
- fprintf(stderr, "no --boot-dex-file specified with --boot\n");
+ fprintf(stderr, "no --boot-dex-file values specified with --boot\n");
return EXIT_FAILURE;
}
}
std::vector<const DexFile*> dex_files;
- OpenDexFiles(dex_filenames, dex_files, strip_location_prefix);
+ DexFile::OpenDexFiles(dex_filenames, dex_files, strip_location_prefix);
std::vector<const DexFile*> boot_dex_files;
- OpenDexFiles(boot_dex_filenames, boot_dex_files, strip_location_prefix);
+ DexFile::OpenDexFiles(boot_dex_filenames, boot_dex_files, strip_location_prefix);
Runtime::Options options;
if (boot_image_option.empty()) {
diff --git a/src/dex_file.cc b/src/dex_file.cc
index 71fd5a7..46fb2dc 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -42,6 +42,20 @@
reinterpret_cast<const DexFile::ClassDef*>(NULL));
}
+void DexFile::OpenDexFiles(std::vector<const char*>& dex_filenames,
+ std::vector<const DexFile*>& dex_files,
+ const std::string& strip_location_prefix) {
+ for (size_t i = 0; i < dex_filenames.size(); i++) {
+ const char* dex_filename = dex_filenames[i];
+ const DexFile* dex_file = Open(dex_filename, strip_location_prefix);
+ if (dex_file == NULL) {
+ fprintf(stderr, "could not open .dex from file %s\n", dex_filename);
+ exit(EXIT_FAILURE);
+ }
+ dex_files.push_back(dex_file);
+ }
+}
+
const DexFile* DexFile::Open(const std::string& filename,
const std::string& strip_location_prefix) {
if (filename.size() < 4) {
diff --git a/src/dex_file.h b/src/dex_file.h
index e4f68e8..3a9d58a 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -316,6 +316,11 @@
static ClassPathEntry FindInClassPath(const StringPiece& descriptor,
const ClassPath& class_path);
+ // Opens a collection of .dex files
+ static void OpenDexFiles(std::vector<const char*>& dex_filenames,
+ std::vector<const DexFile*>& dex_files,
+ const std::string& strip_location_prefix);
+
// Opens .dex file, guessing the format based on file extension
static const DexFile* Open(const std::string& filename,
const std::string& strip_location_prefix);
@@ -699,18 +704,18 @@
// Callback for "new position table entry".
// Returning true causes the decoder to stop early.
- typedef bool (*DexDebugNewPositionCb)(void *cnxt, uint32_t address, uint32_t line_num);
+ typedef bool (*DexDebugNewPositionCb)(void* cnxt, uint32_t address, uint32_t line_num);
// Callback for "new locals table entry". "signature" is an empty string
// if no signature is available for an entry.
- typedef void (*DexDebugNewLocalCb)(void *cnxt, uint16_t reg,
+ typedef void (*DexDebugNewLocalCb)(void* cnxt, uint16_t reg,
uint32_t startAddress,
uint32_t endAddress,
const String* name,
const String* descriptor,
const String* signature);
- static bool LineNumForPcCb(void *cnxt, uint32_t address, uint32_t line_num) {
+ static bool LineNumForPcCb(void* cnxt, uint32_t address, uint32_t line_num) {
LineNumFromPcContext *context = (LineNumFromPcContext *)cnxt;
// We know that this callback will be called in
@@ -775,8 +780,8 @@
DISALLOW_COPY_AND_ASSIGN(LineNumFromPcContext);
};
- void InvokeLocalCbIfLive(void *cnxt, int reg, uint32_t end_address,
- LocalInfo *local_in_reg, DexDebugNewLocalCb local_cb) const {
+ void InvokeLocalCbIfLive(void* cnxt, int reg, uint32_t end_address,
+ LocalInfo* local_in_reg, DexDebugNewLocalCb local_cb) const {
if (local_cb != NULL && local_in_reg[reg].is_live_) {
local_cb(cnxt, reg, local_in_reg[reg].start_address_, end_address,
local_in_reg[reg].name_, local_in_reg[reg].descriptor_,
diff --git a/src/heap.cc b/src/heap.cc
index 72de03f..4778611 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -212,7 +212,7 @@
}
}
-void Heap::VerificationCallback(Object* obj, void *arg) {
+void Heap::VerificationCallback(Object* obj, void* arg) {
DCHECK(obj != NULL);
Heap::VerifyObjectLocked(obj);
}
diff --git a/src/heap.h b/src/heap.h
index ab7564a..e95cfcc 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -174,7 +174,7 @@
static void VerifyObjectLocked(const Object *obj);
- static void VerificationCallback(Object* obj, void *arg);
+ static void VerificationCallback(Object* obj, void* arg);
static Mutex* lock_;
diff --git a/src/image.h b/src/image.h
index 0694630..e3fa35d 100644
--- a/src/image.h
+++ b/src/image.h
@@ -21,7 +21,7 @@
memcpy(version_, kImageVersion, sizeof(kImageVersion));
}
- bool IsValid() {
+ bool IsValid() const {
if (memcmp(magic_, kImageMagic, sizeof(kImageMagic) != 0)) {
return false;
}
@@ -31,6 +31,11 @@
return true;
}
+ const char* GetMagic() const {
+ CHECK(IsValid());
+ return reinterpret_cast<const char*>(magic_);
+ }
+
byte* GetBaseAddr() const {
return reinterpret_cast<byte*>(base_addr_);
}
diff --git a/src/image_writer.cc b/src/image_writer.cc
index 17171bb..ae6c1c8 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -57,7 +57,7 @@
return true;
}
-void ImageWriter::CalculateNewObjectOffsetsCallback(Object* obj, void *arg) {
+void ImageWriter::CalculateNewObjectOffsetsCallback(Object* obj, void* arg) {
DCHECK(obj != NULL);
DCHECK(arg != NULL);
ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg);
@@ -141,7 +141,7 @@
FixupDexCaches();
}
-void ImageWriter::CopyAndFixupObjectsCallback(Object* object, void *arg) {
+void ImageWriter::CopyAndFixupObjectsCallback(Object* object, void* arg) {
DCHECK(object != NULL);
DCHECK(arg != NULL);
const Object* obj = object;
diff --git a/src/image_writer.h b/src/image_writer.h
index a5d3d6a..e91be01 100644
--- a/src/image_writer.h
+++ b/src/image_writer.h
@@ -82,10 +82,10 @@
}
void CalculateNewObjectOffsets();
- static void CalculateNewObjectOffsetsCallback(Object* obj, void *arg);
+ static void CalculateNewObjectOffsetsCallback(Object* obj, void* arg);
void CopyAndFixupObjects();
- static void CopyAndFixupObjectsCallback(Object* obj, void *arg);
+ static void CopyAndFixupObjectsCallback(Object* obj, void* arg);
void FixupClass(const Class* orig, Class* copy);
void FixupMethod(const Method* orig, Method* copy);
void FixupObject(const Object* orig, Object* copy);
diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc
index c947da3..4965692 100644
--- a/src/mark_sweep.cc
+++ b/src/mark_sweep.cc
@@ -146,7 +146,7 @@
SweepJniWeakGlobals();
}
-void MarkSweep::SweepCallback(size_t num_ptrs, void **ptrs, void *arg) {
+void MarkSweep::SweepCallback(size_t num_ptrs, void** ptrs, void* arg) {
// TODO, lock heap if concurrent
Space* space = static_cast<Space*>(arg);
for (size_t i = 0; i < num_ptrs; ++i) {
diff --git a/src/oatdump.cc b/src/oatdump.cc
new file mode 100644
index 0000000..7578fb1
--- /dev/null
+++ b/src/oatdump.cc
@@ -0,0 +1,230 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string>
+#include <vector>
+
+#include "class_linker.h"
+#include "image.h"
+#include "runtime.h"
+#include "space.h"
+#include "stringpiece.h"
+
+namespace art {
+
+static void usage() {
+ fprintf(stderr,
+ "Usage: oatdump [options] ...\n"
+ " Example: oatdump --dex-file=$ANDROID_PRODUCT_OUT/system/framework/core.jar --image=$ANDROID_PRODUCT_OUT/system/framework/boot.oat --strip-prefix=$ANDROID_PRODUCT_OUT\n"
+ " Example: adb shell oatdump --dex-file=/system/framework/core.jar --image=/system/framework/boot.oat\n"
+ "\n");
+ // TODO: remove this by making image contain boot DexFile information?
+ fprintf(stderr,
+ " --dex-file=<dex-file>: specifies a .dex file location. At least one .dex\n"
+ " file must be specified. \n"
+ " Example: --dex-file=/system/framework/core.jar\n"
+ "\n");
+ fprintf(stderr,
+ " --image=<file>: specifies the required input image filename.\n"
+ " Example: --image=/system/framework/boot.oat\n"
+ "\n");
+ fprintf(stderr,
+ " --boot=<oat-file>: provide the oat file for the boot class path.\n"
+ " Example: --boot=/system/framework/boot.oat\n"
+ "\n");
+ // TODO: remove this by making boot image contain boot DexFile information?
+ fprintf(stderr,
+ " --boot-dex-file=<dex-file>: specifies a .dex file that is part of the boot\n"
+ " image specified with --boot. \n"
+ " Example: --boot-dex-file=/system/framework/core.jar\n"
+ "\n");
+ fprintf(stderr,
+ " --strip-prefix may be used to strip a path prefix from dex file names in the\n"
+ " the generated image to match the target file system layout.\n"
+ " Example: --strip-prefix=out/target/product/crespo\n"
+ "\n");
+ exit(EXIT_FAILURE);
+}
+
+const char* image_roots_descriptions_[ImageHeader::kImageRootsMax] = {
+ "kJniStubArray",
+};
+
+struct OatDump {
+ const Space* dump_space;
+
+ bool InDumpSpace(const Object* object) {
+ DCHECK(dump_space != NULL);
+ const byte* o = reinterpret_cast<const byte*>(object);
+ return (o >= dump_space->GetBase() && o < dump_space->GetLimit());
+ }
+
+ static void Callback(Object* obj, void* arg) {
+ DCHECK(obj != NULL);
+ DCHECK(arg != NULL);
+ OatDump* state = reinterpret_cast<OatDump*>(arg);
+ if (!state->InDumpSpace(obj)) {
+ return;
+ }
+ std::string summary;
+ StringAppendF(&summary, "%p: ", obj);
+ if (obj->IsClass()) {
+ Class* klass = obj->AsClass();
+ StringAppendF(&summary, "CLASS %s", klass->GetDescriptor()->ToModifiedUtf8().c_str());
+ } else if (obj->IsMethod()) {
+ Method* method = obj->AsMethod();
+ StringAppendF(&summary, "METHOD %s", PrettyMethod(method).c_str());
+ } else if (obj->IsField()) {
+ Field* field = obj->AsField();
+ Class* type = field->GetType();
+ std::string type_string;
+ type_string += (type == NULL) ? "<UNKNOWN>" : type->GetDescriptor()->ToModifiedUtf8();
+ StringAppendF(&summary, "FIELD %s", PrettyField(field).c_str());
+ } else if (obj->IsArrayInstance()) {
+ StringAppendF(&summary, "ARRAY %d", obj->AsArray()->GetLength());
+ } else if (obj->IsString()) {
+ StringAppendF(&summary, "STRING %s", obj->AsString()->ToModifiedUtf8().c_str());
+ } else {
+ StringAppendF(&summary, "OBJECT");
+ }
+ StringAppendF(&summary, "\n");
+ StringAppendF(&summary, "\tclass %p: %s\n",
+ obj->GetClass(), obj->GetClass()->GetDescriptor()->ToModifiedUtf8().c_str());
+ if (obj->IsMethod()) {
+ Method* method = obj->AsMethod();
+ const ByteArray* code = method->GetCodeArray();
+ StringAppendF(&summary, "\tCODE %p-%p\n", code->GetData(), code->GetData() + code->GetLength());
+ const ByteArray* invoke = method->GetInvokeStubArray();
+ StringAppendF(&summary, "\tJNI STUB %p-%p\n", invoke->GetData(), invoke->GetData() + invoke->GetLength());
+ if (method->IsNative()) {
+ if (method->IsRegistered()) {
+ StringAppendF(&summary, "\tNATIVE REGISTERED %p\n", method->GetNativeMethod());
+ } else {
+ StringAppendF(&summary, "\tNATIVE UNREGISTERED\n");
+ }
+ }
+ }
+ std::cout << summary;
+ }
+};
+
+int oatdump(int argc, char** argv) {
+ // Skip over argv[0].
+ argv++;
+ argc--;
+
+ if (argc == 0) {
+ fprintf(stderr, "no arguments specified\n");
+ usage();
+ }
+
+ std::vector<const char*> dex_filenames;
+ const char* image_filename = NULL;
+ const char* boot_image_filename = NULL;
+ std::vector<const char*> boot_dex_filenames;
+ std::string strip_location_prefix;
+
+ for (int i = 0; i < argc; i++) {
+ const StringPiece option(argv[i]);
+ if (option.starts_with("--dex-file=")) {
+ dex_filenames.push_back(option.substr(strlen("--dex-file=")).data());
+ } else if (option.starts_with("--image=")) {
+ image_filename = option.substr(strlen("--image=")).data();
+ } else if (option.starts_with("--boot=")) {
+ boot_image_filename = option.substr(strlen("--boot=")).data();
+ } else if (option.starts_with("--boot-dex-file=")) {
+ boot_dex_filenames.push_back(option.substr(strlen("--boot-dex-file=")).data());
+ } else if (option.starts_with("--strip-prefix=")) {
+ strip_location_prefix = option.substr(strlen("--strip-prefix=")).data();
+ } else {
+ fprintf(stderr, "unknown argument %s\n", option.data());
+ usage();
+ }
+ }
+
+ if (image_filename == NULL) {
+ fprintf(stderr, "--image file name not specified\n");
+ return EXIT_FAILURE;
+ }
+
+ if (dex_filenames.empty()) {
+ fprintf(stderr, "no --dex-file values specified\n");
+ return EXIT_FAILURE;
+ }
+
+ if (boot_image_filename != NULL && boot_dex_filenames.empty()) {
+ fprintf(stderr, "no --boot-dex-file values specified with --boot\n");
+ return EXIT_FAILURE;
+ }
+
+ std::vector<const DexFile*> dex_files;
+ DexFile::OpenDexFiles(dex_filenames, dex_files, strip_location_prefix);
+
+ std::vector<const DexFile*> boot_dex_files;
+ DexFile::OpenDexFiles(boot_dex_filenames, boot_dex_files, strip_location_prefix);
+
+ Runtime::Options options;
+ std::string image_option;
+ std::string boot_image_option;
+ if (boot_image_filename == NULL) {
+ // if we don't have multiple images, pass the main one as the boot to match dex2oat
+ boot_image_filename = image_filename;
+ boot_dex_files = dex_files;
+ image_filename = NULL;
+ dex_files.clear();
+ } else {
+ image_option += "-Ximage:";
+ image_option += image_filename;
+ options.push_back(std::make_pair("classpath", &dex_files));
+ options.push_back(std::make_pair(image_option.c_str(), reinterpret_cast<void*>(NULL)));
+ }
+ boot_image_option += "-Xbootimage:";
+ boot_image_option += boot_image_filename;
+ options.push_back(std::make_pair("bootclasspath", &boot_dex_files));
+ options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
+
+ UniquePtr<Runtime> runtime(Runtime::Create(options, false));
+ if (runtime.get() == NULL) {
+ fprintf(stderr, "could not create runtime\n");
+ return EXIT_FAILURE;
+ }
+ ClassLinker* class_linker = runtime->GetClassLinker();
+ for (size_t i = 0; i < dex_files.size(); i++) {
+ class_linker->RegisterDexFile(*dex_files[i]);
+ }
+
+ Space* image_space = Heap::GetSpaces()[Heap::GetSpaces().size()-2];
+ CHECK(image_space != NULL);
+ const ImageHeader& image_header = image_space->GetImageHeader();
+ if (!image_header.IsValid()) {
+ fprintf(stderr, "invalid image header %s\n", image_filename);
+ return EXIT_FAILURE;
+ }
+
+ printf("MAGIC:\n");
+ printf("%s\n\n", image_header.GetMagic());
+
+ printf("ROOTS:\n");
+ for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
+ ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i);
+ printf("%s: %p\n", image_roots_descriptions_[i], image_header.GetImageRoot(image_root));
+ }
+ printf("\n");
+
+ printf("OBJECTS:\n");
+ OatDump state;
+ state.dump_space = image_space;
+ HeapBitmap* heap_bitmap = Heap::GetLiveBits();
+ DCHECK(heap_bitmap != NULL);
+ heap_bitmap->Walk(OatDump::Callback, &state);
+
+ return EXIT_SUCCESS;
+}
+
+} // namespace art
+
+int main(int argc, char** argv) {
+ return art::oatdump(argc, argv);
+}
diff --git a/src/oatexec.cc b/src/oatexec.cc
index ca976af..68c67e1 100644
--- a/src/oatexec.cc
+++ b/src/oatexec.cc
@@ -29,7 +29,8 @@
fprintf(stderr, "Unable to find class Method\n");
return false;
}
-#if 0 // TODO: try restoring once iftable_ moved to managed heap
+ static const int PUBLIC = 0x0001; // java.lang.reflect.Modifiers.PUBLIC
+#if 0 // reflect.Method.getModifiers not yet implemented
jmethodID get_modifiers = env->GetMethodID(method.get(),
"getModifiers",
"()I");
@@ -37,9 +38,6 @@
fprintf(stderr, "Unable to find reflect.Method.getModifiers\n");
return false;
}
-#endif
- static const int PUBLIC = 0x0001; // java.lang.reflect.Modifiers.PUBLIC
-#if 0 // CallIntMethod not yet implemented
int modifiers = env->CallIntMethod(reflected.get(), get_modifiers);
#else
int modifiers = PUBLIC;
diff --git a/src/object.h b/src/object.h
index 7292582..5ecd995 100644
--- a/src/object.h
+++ b/src/object.h
@@ -918,6 +918,10 @@
return OFFSET_OF_OBJECT_MEMBER(Method, native_method_);
}
+ const void* GetNativeMethod() const {
+ return reinterpret_cast<const void*>(GetField32(NativeMethodOffset(), false));
+ }
+
ByteArray* GetInvokeStubArray() const {
ByteArray* result = GetFieldPtr<ByteArray*>(
OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_array_), false);
diff --git a/src/object_bitmap.h b/src/object_bitmap.h
index dd23d15..964c914 100644
--- a/src/object_bitmap.h
+++ b/src/object_bitmap.h
@@ -48,11 +48,11 @@
public:
static const size_t kAlignment = 8;
- typedef void Callback(Object* obj, void *arg);
+ typedef void Callback(Object* obj, void* arg);
- typedef void ScanCallback(Object* obj, void *finger, void *arg);
+ typedef void ScanCallback(Object* obj, void* finger, void* arg);
- typedef void SweepCallback(size_t numPtrs, void **ptrs, void *arg);
+ typedef void SweepCallback(size_t numPtrs, void** ptrs, void* arg);
static HeapBitmap* Create(byte* base, size_t length);
diff --git a/src/runtime.cc b/src/runtime.cc
index c21dcc5..d82f255 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -220,6 +220,19 @@
return NULL;
}
parsed->boot_class_path_ = *v;
+ } else if (option == "classpath") {
+ const void* dex_vector = options[i].second;
+ const std::vector<const DexFile*>* v
+ = reinterpret_cast<const std::vector<const DexFile*>*>(dex_vector);
+ if (v == NULL) {
+ if (ignore_unrecognized) {
+ continue;
+ }
+ // TODO: usage
+ LOG(FATAL) << "Failed to parse " << option;
+ return NULL;
+ }
+ parsed->class_path_ = *v;
} else if (option == "-classpath" || option == "-cp") {
// TODO: support -Djava.class.path
i++;
@@ -296,12 +309,17 @@
}
// Consider it an error if both bootclasspath and -Xbootclasspath: are supplied.
- // TODO: remove bootclasspath which is only mostly just used by tests?
+ // TODO: remove bootclasspath and classpath which are mostly just used by tests?
if (!parsed->boot_class_path_.empty() && !parsed->boot_class_path_string_.empty()) {
// TODO: usage
LOG(FATAL) << "bootclasspath and -Xbootclasspath: are mutually exclusive options.";
return NULL;
}
+ if (!parsed->class_path_.empty() && !parsed->class_path_string_.empty()) {
+ // TODO: usage
+ LOG(FATAL) << "bootclasspath and -Xbootclasspath: are mutually exclusive options.";
+ return NULL;
+ }
if (parsed->boot_class_path_.empty()) {
if (parsed->boot_class_path_string_ == NULL) {
const char* BOOTCLASSPATH = getenv("BOOTCLASSPATH");
@@ -310,14 +328,15 @@
CreateClassPath(parsed->boot_class_path_string_, parsed->boot_class_path_);
}
- if (parsed->class_path_string_ == NULL) {
- const char* CLASSPATH = getenv("CLASSPATH");
- if (CLASSPATH != NULL) {
- parsed->class_path_string_ = CLASSPATH;
+ if (parsed->class_path_.empty()) {
+ if (parsed->class_path_string_ == NULL) {
+ const char* CLASSPATH = getenv("CLASSPATH");
+ if (CLASSPATH != NULL) {
+ parsed->class_path_string_ = CLASSPATH;
+ }
}
+ CreateClassPath(parsed->class_path_string_, parsed->class_path_);
}
- CHECK_EQ(parsed->class_path_.size(), 0U);
- CreateClassPath(parsed->class_path_string_, parsed->class_path_);
return parsed.release();
}
diff --git a/src/thread.cc b/src/thread.cc
index 513c019..0da46b6 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -374,7 +374,7 @@
return *reinterpret_cast<Method**>(next_sp);
}
-void* Thread::CreateCallback(void *arg) {
+void* Thread::CreateCallback(void* arg) {
Thread* self = reinterpret_cast<Thread*>(arg);
Runtime* runtime = Runtime::Current();