Add ELF loader to load the executables.
(cherry picked from commit 8c9ca414a7ed05c3530973c63496e477e9ca5eb7)
Conflicts:
src/compiler.cc
Change-Id: I950749625d5b266990c617e2d8cea688fbdc11fb
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index 84e66de..1d878c9 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -18,8 +18,10 @@
#include "class_linker.h"
#include "compilation_unit.h"
+#include "compiled_method.h"
#include "compiler.h"
#include "dex_cache.h"
+#include "elf_loader.h"
#include "ir_builder.h"
#include "jni_compiler.h"
#include "method_compiler.h"
@@ -166,11 +168,64 @@
// Materialize the llvm::Module into ELF object file
curr_cunit_->Materialize();
+ // Load ELF image when automatic ELF loading is enabled
+ if (IsAutoElfLoadingEnabled()) {
+ LoadElfFromCompilationUnit(curr_cunit_);
+ }
+
// Delete the compilation unit
curr_cunit_ = NULL;
}
+void CompilerLLVM::EnableAutoElfLoading() {
+ MutexLock GUARD(compiler_lock_);
+
+ if (IsAutoElfLoadingEnabled()) {
+ // If there is an existing ELF loader, then do nothing.
+ // Because the existing ELF loader may have returned some code address
+ // already. If we replace the existing ELF loader with
+ // elf_loader_.reset(...), then it is possible to have some dangling
+ // pointer.
+ return;
+ }
+
+ // Create ELF loader and load the materialized CompilationUnit
+ elf_loader_.reset(new ElfLoader());
+
+ for (size_t i = 0; i < cunits_.size(); ++i) {
+ if (cunits_[i]->IsMaterialized()) {
+ LoadElfFromCompilationUnit(cunits_[i]);
+ }
+ }
+}
+
+
+void CompilerLLVM::LoadElfFromCompilationUnit(const CompilationUnit* cunit) {
+ compiler_lock_.AssertHeld();
+ DCHECK(cunit->IsMaterialized()) << cunit->GetElfIndex();
+
+ if (!elf_loader_->LoadElfAt(cunit->GetElfIndex(),
+ cunit->GetElfImage(),
+ cunit->GetElfSize())) {
+ LOG(ERROR) << "Failed to load ELF from compilation unit "
+ << cunit->GetElfIndex();
+ }
+}
+
+
+const void* CompilerLLVM::GetMethodCodeAddr(const CompiledMethod* cm,
+ const Method* method) const {
+ return elf_loader_->GetMethodCodeAddr(cm->GetElfIndex(), method);
+}
+
+
+const Method::InvokeStub* CompilerLLVM::
+GetMethodInvokeStubAddr(const CompiledInvokeStub* cm, const Method* method) const {
+ return elf_loader_->GetMethodInvokeStubAddr(cm->GetElfIndex(), method);
+}
+
+
CompiledMethod* CompilerLLVM::
CompileDexMethod(OatCompilationUnit* oat_compilation_unit) {
MutexLock GUARD(compiler_lock_);
@@ -286,6 +341,28 @@
ContextOf(compiler)->MaterializeRemainder();
}
+extern "C" void compilerLLVMEnableAutoElfLoading(art::Compiler& compiler) {
+ art::compiler_llvm::CompilerLLVM* compiler_llvm =
+ reinterpret_cast<art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
+ return compiler_llvm->EnableAutoElfLoading();
+}
+
+extern "C" const void* compilerLLVMGetMethodCodeAddr(const art::Compiler& compiler,
+ const art::CompiledMethod* cm,
+ const art::Method* method) {
+ const art::compiler_llvm::CompilerLLVM* compiler_llvm =
+ reinterpret_cast<const art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
+ return compiler_llvm->GetMethodCodeAddr(cm, method);
+}
+
+extern "C" const art::Method::InvokeStub* compilerLLVMGetMethodInvokeStubAddr(const art::Compiler& compiler,
+ const art::CompiledInvokeStub* cm,
+ const art::Method* method) {
+ const art::compiler_llvm::CompilerLLVM* compiler_llvm =
+ reinterpret_cast<const art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
+ return compiler_llvm->GetMethodInvokeStubAddr(cm, method);
+}
+
// Note: Using this function carefully!!! This is temporary solution, we will remove it.
extern "C" art::MutexLock* compilerLLVMMutexLock(art::Compiler& compiler) {
return new art::MutexLock(ContextOf(compiler)->compiler_lock_);
diff --git a/src/compiler_llvm/compiler_llvm.h b/src/compiler_llvm/compiler_llvm.h
index 562a1d2..626c13d 100644
--- a/src/compiler_llvm/compiler_llvm.h
+++ b/src/compiler_llvm/compiler_llvm.h
@@ -20,6 +20,7 @@
#include "constants.h"
#include "dex_file.h"
#include "macros.h"
+#include "object.h"
#include <UniquePtr.h>
@@ -31,6 +32,7 @@
class CompiledMethod;
class Compiler;
class OatCompilationUnit;
+ class Method;
}
@@ -48,6 +50,7 @@
namespace compiler_llvm {
class CompilationUnit;
+class ElfLoader;
class IRBuilder;
class CompilerLLVM {
@@ -84,6 +87,19 @@
bitcode_filename_ = filename;
}
+ void EnableAutoElfLoading();
+
+ bool IsAutoElfLoadingEnabled() const {
+ return (elf_loader_.get() != NULL);
+ }
+
+ const void* GetMethodCodeAddr(const CompiledMethod* cm,
+ const Method* method) const;
+
+ const Method::InvokeStub* GetMethodInvokeStubAddr(
+ const CompiledInvokeStub* cm,
+ const Method* method) const;
+
CompiledMethod* CompileDexMethod(OatCompilationUnit* oat_compilation_unit);
CompiledMethod* CompileNativeMethod(OatCompilationUnit* oat_compilation_unit);
@@ -95,6 +111,8 @@
void Materialize();
+ void LoadElfFromCompilationUnit(const CompilationUnit* cunit);
+
bool IsBitcodeFileNameAvailable() const {
return !bitcode_filename_.empty();
}
@@ -115,6 +133,8 @@
std::string bitcode_filename_;
+ UniquePtr<ElfLoader> elf_loader_;
+
DISALLOW_COPY_AND_ASSIGN(CompilerLLVM);
};
diff --git a/src/compiler_llvm/elf_loader.cc b/src/compiler_llvm/elf_loader.cc
new file mode 100644
index 0000000..f309b82
--- /dev/null
+++ b/src/compiler_llvm/elf_loader.cc
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "elf_loader.h"
+
+#include "compiled_method.h"
+#include "logging.h"
+#include "object.h"
+#include "runtime_support_llvm.h"
+#include "utils_llvm.h"
+
+#include <android/librsloader.h>
+
+namespace art {
+namespace compiler_llvm {
+
+
+ElfLoader::~ElfLoader() {
+ // Release every ELF object
+ for (size_t i = 0; i < executables_.size(); ++i) {
+ rsloaderDisposeExec(executables_[i]);
+ }
+}
+
+
+bool ElfLoader::LoadElfAt(size_t elf_idx, const byte* image, size_t size) {
+ if (elf_idx < executables_.size() && executables_[elf_idx] != NULL) {
+ return false;
+ }
+
+ if (elf_idx >= executables_.size()) {
+ executables_.resize(elf_idx + 1);
+ }
+
+ RSExecRef executable =
+ rsloaderCreateExec(reinterpret_cast<const unsigned char*>(image),
+ size, art_find_runtime_support_func, NULL);
+
+ if (executable == NULL) {
+ LOG(WARNING) << "Failed to load ELF image: " << image << " size: " << size;
+ return false;
+ }
+
+ executables_[elf_idx] = executable;
+ return true;
+}
+
+
+const void* ElfLoader::GetMethodCodeAddr(size_t elf_idx,
+ const Method* method) const {
+ CHECK_LT(elf_idx, executables_.size());
+ CHECK(method != NULL);
+ return GetAddr(elf_idx, LLVMLongName(method).c_str());
+}
+
+
+const Method::InvokeStub* ElfLoader::
+GetMethodInvokeStubAddr(size_t elf_idx, const Method* method) const {
+ CHECK_LT(elf_idx, executables_.size());
+ CHECK(method != NULL);
+ return reinterpret_cast<const Method::InvokeStub*>(
+ GetAddr(elf_idx, LLVMStubName(method).c_str()));
+}
+
+
+const void* ElfLoader::GetAddr(size_t elf_idx, const char* sym_name) const {
+ CHECK_LT(elf_idx, executables_.size());
+ CHECK(executables_[elf_idx] != NULL);
+ return rsloaderGetSymbolAddress(executables_[elf_idx], sym_name);
+}
+
+
+} // namespace compiler_llvm
+} // namespace art
diff --git a/src/compiler_llvm/elf_loader.h b/src/compiler_llvm/elf_loader.h
new file mode 100644
index 0000000..5f7ab86
--- /dev/null
+++ b/src/compiler_llvm/elf_loader.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_COMPILER_LLVM_ELF_LOADER_H_
+#define ART_SRC_COMPILER_LLVM_ELF_LOADER_H_
+
+#include "globals.h"
+#include "object.h"
+
+#include <android/librsloader.h>
+#include <vector>
+
+namespace art {
+ class Method;
+}
+
+namespace art {
+namespace compiler_llvm {
+
+class ElfLoader {
+ public:
+ ~ElfLoader();
+
+ bool LoadElfAt(size_t elf_idx, const byte* addr, size_t size);
+
+ const void* GetMethodCodeAddr(size_t elf_idx, const Method* method) const;
+
+ const Method::InvokeStub* GetMethodInvokeStubAddr(size_t elf_idx,
+ const Method* method) const;
+
+ private:
+ const void* GetAddr(size_t elf_idx, const char* sym_name) const;
+
+ std::vector<RSExecRef> executables_;
+};
+
+
+} // namespace compiler_llvm
+} // namespace art
+
+#endif // ART_SRC_COMPILER_LLVM_ELF_LOADER_H_
diff --git a/src/compiler_llvm/utils_llvm.cc b/src/compiler_llvm/utils_llvm.cc
index 0941b3e..98d1c7c 100644
--- a/src/compiler_llvm/utils_llvm.cc
+++ b/src/compiler_llvm/utils_llvm.cc
@@ -108,40 +108,4 @@
return stub_name;
}
-void LLVMLinkLoadMethod(const std::string& file_name, Method* method) {
- CHECK(method != NULL);
-
- int fd = open(file_name.c_str(), O_RDONLY);
- CHECK(fd >= 0) << "Error: ELF not found: " << file_name;
-
- struct stat sb;
- CHECK(fstat(fd, &sb) == 0) << "Error: Unable to stat ELF: " << file_name;
-
- unsigned char const *image = (unsigned char const *)
- mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- CHECK(image != MAP_FAILED) << "Error: Unable to mmap ELF: " << file_name;
-
- RSExecRef relocatable =
- rsloaderCreateExec(image, sb.st_size, art_find_runtime_support_func, 0);
- CHECK(relocatable) << "Error: Unable to load ELF: " << file_name;
-
- const void *addr = rsloaderGetSymbolAddress(relocatable, LLVMLongName(method).c_str());
- CHECK(addr) << "Error: ELF (" << file_name << ") has no symbol " << LLVMLongName(method);
- method->SetCode(reinterpret_cast<const uint32_t*>(addr));
-
- method->SetFrameSizeInBytes(0);
- method->SetCoreSpillMask(0);
- method->SetFpSpillMask(0);
- method->SetMappingTable(reinterpret_cast<const uint32_t*>(NULL));
- method->SetVmapTable(reinterpret_cast<const uint16_t*>(NULL));
- method->SetGcMap(reinterpret_cast<const uint8_t*>(NULL));
-
- addr = rsloaderGetSymbolAddress(relocatable, LLVMStubName(method).c_str());
- CHECK(addr) << "Error: ELF (" << file_name << ") has no symbol " << LLVMStubName(method);
- method->SetInvokeStub(reinterpret_cast<void (*)(const art::Method*, art::Object*, art::Thread*,
- art::JValue*, art::JValue*)>(addr));
-
- close(fd);
-}
-
} // namespace art