Add ELF extractor to oatdump.
Change-Id: Ib2d09c07e1b271e033418501b690150cb2063980
diff --git a/src/compiler_llvm/compilation_unit.cc b/src/compiler_llvm/compilation_unit.cc
index d548976..b73e997 100644
--- a/src/compiler_llvm/compilation_unit.cc
+++ b/src/compiler_llvm/compilation_unit.cc
@@ -200,7 +200,7 @@
llvm::OwningPtr<llvm::tool_output_file> out_file(
new llvm::tool_output_file(elf_filename_.c_str(), errmsg,
llvm::raw_fd_ostream::F_Binary));
- out_file->os().write(reinterpret_cast<const char*>(GetElfImage()), GetElfSize());
+ out_file->os().write(elf_image_.data(), elf_image_.size());
out_file->keep();
LOG(INFO) << "ELF: " << elf_filename_ << " (done)";
diff --git a/src/oat_file.cc b/src/oat_file.cc
index 6ae502c..937448c 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -61,6 +61,7 @@
OatFile::~OatFile() {
STLDeleteValues(&oat_dex_files_);
+ STLDeleteElements(&oat_elf_images_);
}
bool OatFile::Map(File& file, byte* requested_base, bool writable) {
@@ -160,6 +161,20 @@
methods_offsets_pointer);
}
+ oat = map->Begin() + oat_header.GetElfImageTableOffset();
+ CHECK((reinterpret_cast<uintptr_t>(oat) & 0x3) == 0);
+
+ for (uint32_t i = 0, end = oat_header.GetElfImageCount(); i < end; ++i) {
+ uint32_t elf_offset = *reinterpret_cast<const uint32_t*>(oat);
+ oat += sizeof(uint32_t);
+
+ uint32_t elf_size = *reinterpret_cast<const uint32_t*>(oat);
+ oat += sizeof(uint32_t);
+
+ oat_elf_images_.push_back(
+ new OatElfImage(this, map->Begin() + elf_offset, elf_size));
+ }
+
mem_map_.reset(map.release());
return true;
}
@@ -314,4 +329,10 @@
method->SetOatInvokeStubOffset(GetInvokeStubOffset());
}
+OatFile::OatElfImage::OatElfImage(const OatFile* oat_file,
+ const byte* addr,
+ uint32_t size)
+ : oat_file_(oat_file), elf_addr_(addr), elf_size_(size) {
+}
+
} // namespace art
diff --git a/src/oat_file.h b/src/oat_file.h
index d75c7c7..2d0f6f8 100644
--- a/src/oat_file.h
+++ b/src/oat_file.h
@@ -211,10 +211,39 @@
DISALLOW_COPY_AND_ASSIGN(OatDexFile);
};
+ class OatElfImage {
+ public:
+ const byte* begin() const {
+ return elf_addr_;
+ }
+
+ const byte* end() const {
+ return (elf_addr_ + elf_size_);
+ }
+
+ size_t size() const {
+ return elf_size_;
+ }
+
+ private:
+ OatElfImage(const OatFile* oat_file, const byte* addr, uint32_t size);
+
+ const OatFile* oat_file_;
+ const byte* elf_addr_;
+ uint32_t elf_size_;
+
+ friend class OatFile;
+ DISALLOW_COPY_AND_ASSIGN(OatElfImage);
+ };
+
const OatDexFile* GetOatDexFile(const std::string& dex_file_location,
bool warn_if_not_found = true) const;
std::vector<const OatDexFile*> GetOatDexFiles() const;
+ const OatElfImage* GetOatElfImage(size_t i) const {
+ return oat_elf_images_[i];
+ }
+
size_t Size() const {
return End() - Begin();
}
@@ -237,6 +266,8 @@
typedef std::map<std::string, const OatDexFile*> Table;
Table oat_dex_files_;
+ std::vector<OatElfImage*> oat_elf_images_;
+
friend class OatClass;
friend class OatDexFile;
friend class OatDumper; // For GetBase and GetLimit
diff --git a/src/oatdump.cc b/src/oatdump.cc
index f38f878..42f8e2a 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -57,6 +57,11 @@
" Example: --boot-image=/system/framework/boot.art\n"
"\n");
fprintf(stderr,
+ " --extract-elf-to=<file.elf>: provide the prefix of the filename for\n"
+ " the output ELF files.\n"
+ " Example: --extract-elf-to=output.elf\n"
+ "\n");
+ fprintf(stderr,
" --host-prefix may be used to translate host paths to target paths during\n"
" cross compilation.\n"
" Example: --host-prefix=out/target/product/crespo\n"
@@ -108,6 +113,9 @@
os << "DEX FILE COUNT:\n";
os << oat_header.GetDexFileCount() << "\n\n";
+ os << "ELF IMAGE COUNT:\n";
+ os << oat_header.GetElfImageCount() << "\n\n";
+
os << "EXECUTABLE OFFSET:\n";
os << StringPrintf("0x%08x\n\n", oat_header.GetExecutableOffset());
@@ -1086,6 +1094,7 @@
const char* oat_filename = NULL;
const char* image_filename = NULL;
const char* boot_image_filename = NULL;
+ std::string elf_filename_prefix;
UniquePtr<std::string> host_prefix;
std::ostream* os = &std::cout;
UniquePtr<std::ofstream> out;
@@ -1098,6 +1107,8 @@
image_filename = option.substr(strlen("--image=")).data();
} else if (option.starts_with("--boot-image=")) {
boot_image_filename = option.substr(strlen("--boot-image=")).data();
+ } else if (option.starts_with("--extract-elf-to=")) {
+ elf_filename_prefix = option.substr(strlen("--extract-elf-to=")).data();
} else if (option.starts_with("--host-prefix=")) {
host_prefix.reset(new std::string(option.substr(strlen("--host-prefix=")).data()));
} else if (option.starts_with("--output=")) {
@@ -1141,6 +1152,23 @@
}
OatDumper oat_dumper(*host_prefix.get(), *oat_file);
oat_dumper.Dump(*os);
+
+ if (!elf_filename_prefix.empty()) {
+ uint32_t elf_image_count = oat_file->GetOatHeader().GetElfImageCount();
+ for (uint32_t i = 0; i < elf_image_count; ++i) {
+ const OatFile::OatElfImage* elf_image = oat_file->GetOatElfImage(i);
+
+ std::string elf_filename(
+ StringPrintf("%s-%u", elf_filename_prefix.c_str(), i));
+
+ UniquePtr<File> elf_file(OS::OpenFile(elf_filename.c_str(), true));
+
+ if (!elf_file->WriteFully(elf_image->begin(), elf_image->size())) {
+ fprintf(stderr, "Failed to write ELF image to: %s\n",
+ elf_filename.c_str());
+ }
+ }
+ }
return EXIT_SUCCESS;
}