blob: 8432a07013e03c8b2f29ec8391ea8e2b1aac2e8c [file] [log] [blame]
Logan Chienf7015fd2012-03-18 01:19:37 +08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "elf_loader.h"
18
19#include "compiled_method.h"
Logan Chien0f0899a2012-03-23 10:48:18 +080020#include "elf_image.h"
Logan Chienf7015fd2012-03-18 01:19:37 +080021#include "logging.h"
Logan Chien0c717dd2012-03-28 18:31:07 +080022#include "oat_file.h"
Logan Chienf7015fd2012-03-18 01:19:37 +080023#include "object.h"
24#include "runtime_support_llvm.h"
25#include "utils_llvm.h"
26
27#include <android/librsloader.h>
28
29namespace art {
30namespace compiler_llvm {
31
32
33ElfLoader::~ElfLoader() {
34 // Release every ELF object
35 for (size_t i = 0; i < executables_.size(); ++i) {
36 rsloaderDisposeExec(executables_[i]);
37 }
38}
39
40
Logan Chien0c717dd2012-03-28 18:31:07 +080041bool ElfLoader::LoadElfAt(size_t elf_idx,
42 const ElfImage& elf_image,
43 OatFile::RelocationBehavior reloc) {
Logan Chienf7015fd2012-03-18 01:19:37 +080044 if (elf_idx < executables_.size() && executables_[elf_idx] != NULL) {
45 return false;
46 }
47
48 if (elf_idx >= executables_.size()) {
49 executables_.resize(elf_idx + 1);
TDYa1279d93ee62012-05-09 09:56:07 -070050 elf_images_.resize(elf_idx + 1);
Logan Chienf7015fd2012-03-18 01:19:37 +080051 }
52
Logan Chien0c717dd2012-03-28 18:31:07 +080053 RSExecRef executable = rsloaderLoadExecutable(elf_image.begin(),
TDYa1279d93ee62012-05-09 09:56:07 -070054 elf_image.size(),
55 reloc == OatFile::kRelocNone ? 1 : 0);
Logan Chienf7015fd2012-03-18 01:19:37 +080056
57 if (executable == NULL) {
Logan Chien0f0899a2012-03-23 10:48:18 +080058 LOG(WARNING) << "Failed to load ELF"
Logan Chien3fe0c602012-03-27 21:14:37 +080059 << " image: " << static_cast<const void*>(elf_image.begin())
Logan Chien0f0899a2012-03-23 10:48:18 +080060 << " size: " << elf_image.size();
Logan Chienf7015fd2012-03-18 01:19:37 +080061 return false;
62 }
63
Logan Chien0c717dd2012-03-28 18:31:07 +080064 if (reloc == OatFile::kRelocAll) {
65 if (!rsloaderRelocateExecutable(executable,
66 art_find_runtime_support_func, NULL)) {
67 LOG(ERROR) << "Failed to relocate the ELF image";
68 rsloaderDisposeExec(executable);
69 return false;
70 }
TDYa1279d93ee62012-05-09 09:56:07 -070071 relocated = true;
Logan Chien0c717dd2012-03-28 18:31:07 +080072 }
73
Logan Chienf7015fd2012-03-18 01:19:37 +080074 executables_[elf_idx] = executable;
TDYa1279d93ee62012-05-09 09:56:07 -070075 elf_images_[elf_idx] = elf_image;
Logan Chienf7015fd2012-03-18 01:19:37 +080076 return true;
77}
78
79
Logan Chien0c717dd2012-03-28 18:31:07 +080080void ElfLoader::RelocateExecutable() {
TDYa1279d93ee62012-05-09 09:56:07 -070081 if (relocated) {
82 return;
83 }
84 LOG(INFO) << "Reload ELF for relocate.";
Logan Chien0c717dd2012-03-28 18:31:07 +080085 for (size_t i = 0; i < executables_.size(); ++i) {
TDYa1279d93ee62012-05-09 09:56:07 -070086 if (executables_[i] != NULL) {
87 // TODO: After implement in-place linking, we will no longer need to dispose and reload.
88 rsloaderDisposeExec(executables_[i]);
89 executables_[i] = rsloaderLoadExecutable(elf_images_[i].begin(), elf_images_[i].size(), 0);
90 if (executables_[i] == NULL) {
91 LOG(FATAL) << "Failed to reload ELF image " << i;
92 }
93 if (!rsloaderRelocateExecutable(executables_[i],
94 art_find_runtime_support_func, NULL)) {
95 LOG(FATAL) << "Failed to relocate ELF image " << i;
96 }
Logan Chien0c717dd2012-03-28 18:31:07 +080097 }
98 }
TDYa1279d93ee62012-05-09 09:56:07 -070099 relocated = true;
Logan Chien0c717dd2012-03-28 18:31:07 +0800100}
101
102
Logan Chien937105a2012-04-02 02:37:37 +0800103const void* ElfLoader::GetMethodCodeAddr(uint16_t elf_idx,
104 uint16_t elf_func_idx) const {
Logan Chienf7015fd2012-03-18 01:19:37 +0800105 CHECK_LT(elf_idx, executables_.size());
Logan Chien937105a2012-04-02 02:37:37 +0800106 return GetAddr(elf_idx, ElfFuncName(elf_func_idx).c_str());
Logan Chienf7015fd2012-03-18 01:19:37 +0800107}
108
109
110const Method::InvokeStub* ElfLoader::
Logan Chien937105a2012-04-02 02:37:37 +0800111GetMethodInvokeStubAddr(uint16_t elf_idx, uint16_t elf_func_idx) const {
Logan Chienf7015fd2012-03-18 01:19:37 +0800112 CHECK_LT(elf_idx, executables_.size());
Logan Chienf7015fd2012-03-18 01:19:37 +0800113 return reinterpret_cast<const Method::InvokeStub*>(
Logan Chien937105a2012-04-02 02:37:37 +0800114 GetAddr(elf_idx, ElfFuncName(elf_func_idx).c_str()));
Logan Chienf7015fd2012-03-18 01:19:37 +0800115}
116
117
Logan Chien14924fe2012-04-03 18:33:37 +0800118size_t ElfLoader::GetCodeSize(uint16_t elf_idx, uint16_t elf_func_idx) const {
119 CHECK_LT(elf_idx, executables_.size());
120 CHECK(executables_[elf_idx] != NULL);
121 return rsloaderGetSymbolSize(executables_[elf_idx],
122 ElfFuncName(elf_func_idx).c_str());
123}
124
125
Logan Chienf7015fd2012-03-18 01:19:37 +0800126const void* ElfLoader::GetAddr(size_t elf_idx, const char* sym_name) const {
127 CHECK_LT(elf_idx, executables_.size());
128 CHECK(executables_[elf_idx] != NULL);
129 return rsloaderGetSymbolAddress(executables_[elf_idx], sym_name);
130}
131
132
133} // namespace compiler_llvm
134} // namespace art