diff options
| author | 2012-02-23 23:48:21 -0800 | |
|---|---|---|
| committer | 2012-03-01 11:44:02 -0800 | |
| commit | 5b8b1edc803a85bb3172560826d6a23fb23c3452 (patch) | |
| tree | 43fe7644011ad6b8c7175ee9748f5fd27e0d27af /src/compiler_llvm/utils_llvm.cc | |
| parent | 31a4a6f5717f645da6b97ccc1e420ae1e1c71ce0 (diff) | |
Implement Link-loading and pass 62 tests in JniInternalTest.
The passed tests include the 12 originally ARM-only tests. Now it works
on x86 as well if defined(ART_USE_LLVM_COMPILER).
Change-Id: I03092637fa4f0979ca77e0cac06e5d31a867e465
Diffstat (limited to 'src/compiler_llvm/utils_llvm.cc')
| -rw-r--r-- | src/compiler_llvm/utils_llvm.cc | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/src/compiler_llvm/utils_llvm.cc b/src/compiler_llvm/utils_llvm.cc index 1a8e8a211b..a924793dd1 100644 --- a/src/compiler_llvm/utils_llvm.cc +++ b/src/compiler_llvm/utils_llvm.cc @@ -14,6 +14,12 @@ * limitations under the License. */ +#include <android/librsloader.h> +#include <cutils/log.h> +#include <fcntl.h> +#include <string.h> +#include <sys/mman.h> + #include "utils_llvm.h" #include "class_loader.h" @@ -86,4 +92,112 @@ std::string LLVMLongName(const Method* m) { return long_name; } +std::string LLVMStubName(const Method* m) { + MethodHelper mh(m); + std::string stub_name; + if (m->IsStatic()) { + stub_name += "ArtSUpcall_"; + } else { + stub_name += "ArtUpcall_"; + } + stub_name += mh.GetShorty(); + + return stub_name; +} + +// TODO: Remove these when art_llvm.ll runtime support is ready. +void art_push_shadow_frame_from_code(void* frame) { +} + +void art_pop_shadow_frame_from_code() { +} + +int art_is_exception_pending_from_code() { + return 0; +} + +void art_test_suspend_from_code() { +} + +void art_set_current_thread_from_code(void* thread_object_addr) { +} + +// Linker's call back function. Added some for debugging. +void* find_sym(void* context, char const* name) { + struct func_entry_t { + char const* name; + size_t name_len; + void* addr; + }; + + static struct func_entry_t const tab[] = { +#define DEF(NAME, ADDR) \ + { NAME, sizeof(NAME) - 1, (void *)(&(ADDR)) }, + + DEF("art_push_shadow_frame_from_code", art_push_shadow_frame_from_code) + DEF("art_pop_shadow_frame_from_code", art_pop_shadow_frame_from_code) + DEF("art_is_exception_pending_from_code", art_is_exception_pending_from_code) + DEF("art_test_suspend_from_code", art_test_suspend_from_code) + DEF("art_set_current_thread_from_code", art_set_current_thread_from_code) + DEF("printf", printf) + DEF("scanf", scanf) + DEF("__isoc99_scanf", scanf) + DEF("rand", rand) + DEF("time", time) + DEF("srand", srand) +#undef DEF + }; + + static size_t const tab_size = sizeof(tab) / sizeof(struct func_entry_t); + + // Note: Since our table is small, we are using trivial O(n) searching + // function. For bigger table, it will be better to use binary + // search or hash function. + size_t i; + size_t name_len = strlen(name); + for (i = 0; i < tab_size; ++i) { + if (name_len == tab[i].name_len && strcmp(name, tab[i].name) == 0) { + return tab[i].addr; + } + } + + CHECK(0) << "Error: Can't find symbol " << name; + return 0; +} + +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, find_sym, 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::byte*, art::JValue*)>(addr)); + + close(fd); +} + } // namespace art |