blob: 92eb4d895560f59554c5e60703c3e4e573642b7e [file] [log] [blame]
Alex Lighta59dd802014-07-02 16:28:08 -07001/*
2 * Copyright (C) 2014 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_patcher.h"
18
19#include <vector>
20#include <set>
21
Andreas Gampe53c913b2014-08-12 23:19:23 -070022#include "class_linker.h"
Alex Lighta59dd802014-07-02 16:28:08 -070023#include "elf_file.h"
24#include "elf_utils.h"
25#include "mirror/art_field-inl.h"
26#include "mirror/art_method-inl.h"
27#include "mirror/array-inl.h"
28#include "mirror/class-inl.h"
29#include "mirror/class_loader.h"
30#include "mirror/dex_cache-inl.h"
31#include "mirror/object-inl.h"
32#include "mirror/object_array-inl.h"
33#include "mirror/string-inl.h"
34#include "oat.h"
35#include "os.h"
36#include "utils.h"
37
38namespace art {
39
40bool ElfPatcher::Patch(const CompilerDriver* driver, ElfFile* elf_file,
41 const std::string& oat_location,
42 ImageAddressCallback cb, void* cb_data,
43 std::string* error_msg) {
44 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
45 const OatFile* oat_file = class_linker->FindOpenedOatFileFromOatLocation(oat_location);
46 if (oat_file == nullptr) {
47 CHECK(Runtime::Current()->IsCompiler());
48 oat_file = OatFile::Open(oat_location, oat_location, NULL, false, error_msg);
49 if (oat_file == nullptr) {
50 *error_msg = StringPrintf("Unable to find or open oat file at '%s': %s", oat_location.c_str(),
51 error_msg->c_str());
52 return false;
53 }
54 CHECK_EQ(class_linker->RegisterOatFile(oat_file), oat_file);
55 }
56 return ElfPatcher::Patch(driver, elf_file, oat_file,
57 reinterpret_cast<uintptr_t>(oat_file->Begin()), cb, cb_data, error_msg);
58}
59
60bool ElfPatcher::Patch(const CompilerDriver* driver, ElfFile* elf, const OatFile* oat_file,
61 uintptr_t oat_data_start, ImageAddressCallback cb, void* cb_data,
62 std::string* error_msg) {
63 Elf32_Shdr* data_sec = elf->FindSectionByName(".rodata");
64 if (data_sec == nullptr) {
65 *error_msg = "Unable to find .rodata section and oat header";
66 return false;
67 }
68 OatHeader* oat_header = reinterpret_cast<OatHeader*>(elf->Begin() + data_sec->sh_offset);
69 if (!oat_header->IsValid()) {
70 *error_msg = "Oat header was not valid";
71 return false;
72 }
73
74 ElfPatcher p(driver, elf, oat_file, oat_header, oat_data_start, cb, cb_data, error_msg);
75 return p.PatchElf();
76}
77
78mirror::ArtMethod* ElfPatcher::GetTargetMethod(const CompilerDriver::CallPatchInformation* patch) {
79 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
80 StackHandleScope<1> hs(Thread::Current());
81 Handle<mirror::DexCache> dex_cache(
82 hs.NewHandle(class_linker->FindDexCache(*patch->GetTargetDexFile())));
83 mirror::ArtMethod* method = class_linker->ResolveMethod(*patch->GetTargetDexFile(),
84 patch->GetTargetMethodIdx(),
85 dex_cache,
86 NullHandle<mirror::ClassLoader>(),
87 NullHandle<mirror::ArtMethod>(),
88 patch->GetTargetInvokeType());
89 CHECK(method != NULL)
90 << patch->GetTargetDexFile()->GetLocation() << " " << patch->GetTargetMethodIdx();
91 CHECK(!method->IsRuntimeMethod())
92 << patch->GetTargetDexFile()->GetLocation() << " " << patch->GetTargetMethodIdx();
93 CHECK(dex_cache->GetResolvedMethods()->Get(patch->GetTargetMethodIdx()) == method)
94 << patch->GetTargetDexFile()->GetLocation() << " " << patch->GetReferrerMethodIdx() << " "
95 << PrettyMethod(dex_cache->GetResolvedMethods()->Get(patch->GetTargetMethodIdx())) << " "
96 << PrettyMethod(method);
97 return method;
98}
99
100mirror::Class* ElfPatcher::GetTargetType(const CompilerDriver::TypePatchInformation* patch) {
101 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
102 StackHandleScope<2> hs(Thread::Current());
Fred Shihe7f82e22014-08-06 10:46:37 -0700103 Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(
104 patch->GetTargetTypeDexFile())));
105 mirror::Class* klass = class_linker->ResolveType(patch->GetTargetTypeDexFile(),
106 patch->GetTargetTypeIdx(),
Alex Lighta59dd802014-07-02 16:28:08 -0700107 dex_cache, NullHandle<mirror::ClassLoader>());
108 CHECK(klass != NULL)
Fred Shihe7f82e22014-08-06 10:46:37 -0700109 << patch->GetTargetTypeDexFile().GetLocation() << " " << patch->GetTargetTypeIdx();
Alex Lighta59dd802014-07-02 16:28:08 -0700110 CHECK(dex_cache->GetResolvedTypes()->Get(patch->GetTargetTypeIdx()) == klass)
111 << patch->GetDexFile().GetLocation() << " " << patch->GetReferrerMethodIdx() << " "
112 << PrettyClass(dex_cache->GetResolvedTypes()->Get(patch->GetTargetTypeIdx())) << " "
113 << PrettyClass(klass);
114 return klass;
115}
116
117void ElfPatcher::AddPatch(uintptr_t p) {
118 if (write_patches_ && patches_set_.find(p) == patches_set_.end()) {
119 patches_set_.insert(p);
120 patches_.push_back(p);
121 }
122}
123
124uint32_t* ElfPatcher::GetPatchLocation(uintptr_t patch_ptr) {
125 CHECK_GE(patch_ptr, reinterpret_cast<uintptr_t>(oat_file_->Begin()));
Alex Light6e183f22014-07-18 14:57:04 -0700126 CHECK_LE(patch_ptr, reinterpret_cast<uintptr_t>(oat_file_->End()));
Alex Lighta59dd802014-07-02 16:28:08 -0700127 uintptr_t off = patch_ptr - reinterpret_cast<uintptr_t>(oat_file_->Begin());
128 uintptr_t ret = reinterpret_cast<uintptr_t>(oat_header_) + off;
129
130 CHECK_GE(ret, reinterpret_cast<uintptr_t>(elf_file_->Begin()));
131 CHECK_LT(ret, reinterpret_cast<uintptr_t>(elf_file_->End()));
132 return reinterpret_cast<uint32_t*>(ret);
133}
134
135void ElfPatcher::SetPatchLocation(const CompilerDriver::PatchInformation* patch, uint32_t value) {
136 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
137 const void* quick_oat_code = class_linker->GetQuickOatCodeFor(patch->GetDexFile(),
138 patch->GetReferrerClassDefIdx(),
139 patch->GetReferrerMethodIdx());
140 // TODO: make this Thumb2 specific
141 uint8_t* base = reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(quick_oat_code) & ~0x1);
142 uintptr_t patch_ptr = reinterpret_cast<uintptr_t>(base + patch->GetLiteralOffset());
143 uint32_t* patch_location = GetPatchLocation(patch_ptr);
144 if (kIsDebugBuild) {
145 if (patch->IsCall()) {
146 const CompilerDriver::CallPatchInformation* cpatch = patch->AsCall();
147 const DexFile::MethodId& id =
148 cpatch->GetTargetDexFile()->GetMethodId(cpatch->GetTargetMethodIdx());
149 uint32_t expected = reinterpret_cast<uintptr_t>(&id) & 0xFFFFFFFF;
150 uint32_t actual = *patch_location;
Alex Light6e183f22014-07-18 14:57:04 -0700151 CHECK(actual == expected || actual == value) << "Patching call failed: " << std::hex
152 << " actual=" << actual
153 << " expected=" << expected
154 << " value=" << value;
Alex Lighta59dd802014-07-02 16:28:08 -0700155 }
156 if (patch->IsType()) {
157 const CompilerDriver::TypePatchInformation* tpatch = patch->AsType();
Fred Shihe7f82e22014-08-06 10:46:37 -0700158 const DexFile::TypeId& id = tpatch->GetTargetTypeDexFile().GetTypeId(tpatch->GetTargetTypeIdx());
Alex Lighta59dd802014-07-02 16:28:08 -0700159 uint32_t expected = reinterpret_cast<uintptr_t>(&id) & 0xFFFFFFFF;
160 uint32_t actual = *patch_location;
Alex Light6e183f22014-07-18 14:57:04 -0700161 CHECK(actual == expected || actual == value) << "Patching type failed: " << std::hex
162 << " actual=" << actual
163 << " expected=" << expected
164 << " value=" << value;
Alex Lighta59dd802014-07-02 16:28:08 -0700165 }
166 }
167 *patch_location = value;
168 oat_header_->UpdateChecksum(patch_location, sizeof(value));
169
170 if (patch->IsCall() && patch->AsCall()->IsRelative()) {
171 // We never record relative patches.
172 return;
173 }
174 uintptr_t loc = patch_ptr - (reinterpret_cast<uintptr_t>(oat_file_->Begin()) +
175 oat_header_->GetExecutableOffset());
176 CHECK_GT(patch_ptr, reinterpret_cast<uintptr_t>(oat_file_->Begin()) +
177 oat_header_->GetExecutableOffset());
178 CHECK_LT(loc, oat_file_->Size() - oat_header_->GetExecutableOffset());
179 AddPatch(loc);
180}
181
182bool ElfPatcher::PatchElf() {
183 // TODO if we are adding patches the resulting ELF file might have a
184 // potentially rather large amount of free space where patches might have been
185 // placed. We should adjust the ELF file to get rid of this excess space.
186 if (write_patches_) {
187 patches_.reserve(compiler_driver_->GetCodeToPatch().size() +
188 compiler_driver_->GetMethodsToPatch().size() +
189 compiler_driver_->GetClassesToPatch().size());
190 }
191 Thread* self = Thread::Current();
192 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
193 const char* old_cause = self->StartAssertNoThreadSuspension("ElfPatcher");
194
195 typedef std::vector<const CompilerDriver::CallPatchInformation*> CallPatches;
196 const CallPatches& code_to_patch = compiler_driver_->GetCodeToPatch();
197 for (size_t i = 0; i < code_to_patch.size(); i++) {
198 const CompilerDriver::CallPatchInformation* patch = code_to_patch[i];
199
200 mirror::ArtMethod* target = GetTargetMethod(patch);
201 uintptr_t quick_code = reinterpret_cast<uintptr_t>(class_linker->GetQuickOatCodeFor(target));
202 DCHECK_NE(quick_code, 0U) << PrettyMethod(target);
Vladimir Markoaa4497d2014-09-05 14:01:17 +0100203 const OatFile* target_oat =
204 class_linker->FindOpenedOatDexFileForDexFile(*patch->GetTargetDexFile())->GetOatFile();
Alex Lighta59dd802014-07-02 16:28:08 -0700205 // Get where the data actually starts. if target is this oat_file_ it is oat_data_start_,
206 // otherwise it is wherever target_oat is loaded.
207 uintptr_t oat_data_addr = GetBaseAddressFor(target_oat);
208 uintptr_t code_base = reinterpret_cast<uintptr_t>(target_oat->Begin());
209 uintptr_t code_offset = quick_code - code_base;
210 bool is_quick_offset = false;
211 if (quick_code == reinterpret_cast<uintptr_t>(GetQuickToInterpreterBridge())) {
212 is_quick_offset = true;
213 code_offset = oat_header_->GetQuickToInterpreterBridgeOffset();
214 } else if (quick_code ==
215 reinterpret_cast<uintptr_t>(class_linker->GetQuickGenericJniTrampoline())) {
216 CHECK(target->IsNative());
217 is_quick_offset = true;
218 code_offset = oat_header_->GetQuickGenericJniTrampolineOffset();
219 }
220 uintptr_t value;
221 if (patch->IsRelative()) {
222 // value to patch is relative to the location being patched
223 const void* quick_oat_code =
224 class_linker->GetQuickOatCodeFor(patch->GetDexFile(),
225 patch->GetReferrerClassDefIdx(),
226 patch->GetReferrerMethodIdx());
227 if (is_quick_offset) {
228 // If its a quick offset it means that we are doing a relative patch from the class linker
229 // oat_file to the elf_patcher oat_file so we need to adjust the quick oat code to be the
230 // one in the output oat_file (ie where it is actually going to be loaded).
231 quick_code = PointerToLowMemUInt32(reinterpret_cast<void*>(oat_data_addr + code_offset));
232 quick_oat_code =
233 reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(quick_oat_code) +
234 oat_data_addr - code_base);
235 }
236 uintptr_t base = reinterpret_cast<uintptr_t>(quick_oat_code);
237 uintptr_t patch_location = base + patch->GetLiteralOffset();
238 value = quick_code - patch_location + patch->RelativeOffset();
239 } else if (code_offset != 0) {
240 value = PointerToLowMemUInt32(reinterpret_cast<void*>(oat_data_addr + code_offset));
241 } else {
242 value = 0;
243 }
244 SetPatchLocation(patch, value);
245 }
246
247 const CallPatches& methods_to_patch = compiler_driver_->GetMethodsToPatch();
248 for (size_t i = 0; i < methods_to_patch.size(); i++) {
249 const CompilerDriver::CallPatchInformation* patch = methods_to_patch[i];
250 mirror::ArtMethod* target = GetTargetMethod(patch);
251 SetPatchLocation(patch, PointerToLowMemUInt32(get_image_address_(cb_data_, target)));
252 }
253
254 const std::vector<const CompilerDriver::TypePatchInformation*>& classes_to_patch =
255 compiler_driver_->GetClassesToPatch();
256 for (size_t i = 0; i < classes_to_patch.size(); i++) {
257 const CompilerDriver::TypePatchInformation* patch = classes_to_patch[i];
258 mirror::Class* target = GetTargetType(patch);
259 SetPatchLocation(patch, PointerToLowMemUInt32(get_image_address_(cb_data_, target)));
260 }
261
262 self->EndAssertNoThreadSuspension(old_cause);
263
264 if (write_patches_) {
265 return WriteOutPatchData();
266 }
267 return true;
268}
269
270bool ElfPatcher::WriteOutPatchData() {
271 Elf32_Shdr* shdr = elf_file_->FindSectionByName(".oat_patches");
272 if (shdr != nullptr) {
273 CHECK_EQ(shdr, elf_file_->FindSectionByType(SHT_OAT_PATCH))
274 << "Incorrect type for .oat_patches section";
275 CHECK_LE(patches_.size() * sizeof(uintptr_t), shdr->sh_size)
276 << "We got more patches than anticipated";
277 CHECK_LE(reinterpret_cast<uintptr_t>(elf_file_->Begin()) + shdr->sh_offset + shdr->sh_size,
278 reinterpret_cast<uintptr_t>(elf_file_->End())) << "section is too large";
Andreas Gampedaab38c2014-09-12 18:38:24 -0700279 CHECK(shdr == elf_file_->GetSectionHeader(elf_file_->GetSectionHeaderNum() - 1) ||
Alex Lighta59dd802014-07-02 16:28:08 -0700280 shdr->sh_offset + shdr->sh_size <= (shdr + 1)->sh_offset)
281 << "Section overlaps onto next section";
282 // It's mmap'd so we can just memcpy.
283 memcpy(elf_file_->Begin() + shdr->sh_offset, patches_.data(),
284 patches_.size() * sizeof(uintptr_t));
285 // TODO We should fill in the newly empty space between the last patch and
286 // the start of the next section by moving the following sections down if
287 // possible.
288 shdr->sh_size = patches_.size() * sizeof(uintptr_t);
289 return true;
290 } else {
291 LOG(ERROR) << "Unable to find section header for SHT_OAT_PATCH";
292 *error_msg_ = "Unable to find section to write patch information to in ";
293 *error_msg_ += elf_file_->GetFile().GetPath();
294 return false;
295 }
296}
297
298} // namespace art