OSDN Git Service

am b148ad48: am f72fd02c: Merge "Quick compiler: disable GVN DO NOT MERGE" into lmp-dev
[android-x86/art.git] / compiler / elf_patcher.cc
1 /*
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
22 #include "class_linker.h"
23 #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
38 namespace art {
39
40 bool 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
60 bool 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
78 mirror::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
100 mirror::Class* ElfPatcher::GetTargetType(const CompilerDriver::TypePatchInformation* patch) {
101   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
102   StackHandleScope<2> hs(Thread::Current());
103   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(),
107                                                    dex_cache, NullHandle<mirror::ClassLoader>());
108   CHECK(klass != NULL)
109     << patch->GetTargetTypeDexFile().GetLocation() << " " << patch->GetTargetTypeIdx();
110   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
117 void 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
124 uint32_t* ElfPatcher::GetPatchLocation(uintptr_t patch_ptr) {
125   CHECK_GE(patch_ptr, reinterpret_cast<uintptr_t>(oat_file_->Begin()));
126   CHECK_LE(patch_ptr, reinterpret_cast<uintptr_t>(oat_file_->End()));
127   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
135 void 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;
151       CHECK(actual == expected || actual == value) << "Patching call failed: " << std::hex
152           << " actual=" << actual
153           << " expected=" << expected
154           << " value=" << value;
155     }
156     if (patch->IsType()) {
157       const CompilerDriver::TypePatchInformation* tpatch = patch->AsType();
158       const DexFile::TypeId& id = tpatch->GetTargetTypeDexFile().GetTypeId(tpatch->GetTargetTypeIdx());
159       uint32_t expected = reinterpret_cast<uintptr_t>(&id) & 0xFFFFFFFF;
160       uint32_t actual = *patch_location;
161       CHECK(actual == expected || actual == value) << "Patching type failed: " << std::hex
162           << " actual=" << actual
163           << " expected=" << expected
164           << " value=" << value;
165     }
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
182 bool 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);
203     const OatFile* target_oat = class_linker->FindOpenedOatFileForDexFile(*patch->GetTargetDexFile());
204     // Get where the data actually starts. if target is this oat_file_ it is oat_data_start_,
205     // otherwise it is wherever target_oat is loaded.
206     uintptr_t oat_data_addr = GetBaseAddressFor(target_oat);
207     uintptr_t code_base = reinterpret_cast<uintptr_t>(target_oat->Begin());
208     uintptr_t code_offset = quick_code - code_base;
209     bool is_quick_offset = false;
210     if (quick_code == reinterpret_cast<uintptr_t>(GetQuickToInterpreterBridge())) {
211       is_quick_offset = true;
212       code_offset = oat_header_->GetQuickToInterpreterBridgeOffset();
213     } else if (quick_code ==
214         reinterpret_cast<uintptr_t>(class_linker->GetQuickGenericJniTrampoline())) {
215       CHECK(target->IsNative());
216       is_quick_offset = true;
217       code_offset = oat_header_->GetQuickGenericJniTrampolineOffset();
218     }
219     uintptr_t value;
220     if (patch->IsRelative()) {
221       // value to patch is relative to the location being patched
222       const void* quick_oat_code =
223         class_linker->GetQuickOatCodeFor(patch->GetDexFile(),
224                                          patch->GetReferrerClassDefIdx(),
225                                          patch->GetReferrerMethodIdx());
226       if (is_quick_offset) {
227         // If its a quick offset it means that we are doing a relative patch from the class linker
228         // oat_file to the elf_patcher oat_file so we need to adjust the quick oat code to be the
229         // one in the output oat_file (ie where it is actually going to be loaded).
230         quick_code = PointerToLowMemUInt32(reinterpret_cast<void*>(oat_data_addr + code_offset));
231         quick_oat_code =
232             reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(quick_oat_code) +
233                 oat_data_addr - code_base);
234       }
235       uintptr_t base = reinterpret_cast<uintptr_t>(quick_oat_code);
236       uintptr_t patch_location = base + patch->GetLiteralOffset();
237       value = quick_code - patch_location + patch->RelativeOffset();
238     } else if (code_offset != 0) {
239       value = PointerToLowMemUInt32(reinterpret_cast<void*>(oat_data_addr + code_offset));
240     } else {
241       value = 0;
242     }
243     SetPatchLocation(patch, value);
244   }
245
246   const CallPatches& methods_to_patch = compiler_driver_->GetMethodsToPatch();
247   for (size_t i = 0; i < methods_to_patch.size(); i++) {
248     const CompilerDriver::CallPatchInformation* patch = methods_to_patch[i];
249     mirror::ArtMethod* target = GetTargetMethod(patch);
250     SetPatchLocation(patch, PointerToLowMemUInt32(get_image_address_(cb_data_, target)));
251   }
252
253   const std::vector<const CompilerDriver::TypePatchInformation*>& classes_to_patch =
254       compiler_driver_->GetClassesToPatch();
255   for (size_t i = 0; i < classes_to_patch.size(); i++) {
256     const CompilerDriver::TypePatchInformation* patch = classes_to_patch[i];
257     mirror::Class* target = GetTargetType(patch);
258     SetPatchLocation(patch, PointerToLowMemUInt32(get_image_address_(cb_data_, target)));
259   }
260
261   self->EndAssertNoThreadSuspension(old_cause);
262
263   if (write_patches_) {
264     return WriteOutPatchData();
265   }
266   return true;
267 }
268
269 bool ElfPatcher::WriteOutPatchData() {
270   Elf32_Shdr* shdr = elf_file_->FindSectionByName(".oat_patches");
271   if (shdr != nullptr) {
272     CHECK_EQ(shdr, elf_file_->FindSectionByType(SHT_OAT_PATCH))
273         << "Incorrect type for .oat_patches section";
274     CHECK_LE(patches_.size() * sizeof(uintptr_t), shdr->sh_size)
275         << "We got more patches than anticipated";
276     CHECK_LE(reinterpret_cast<uintptr_t>(elf_file_->Begin()) + shdr->sh_offset + shdr->sh_size,
277               reinterpret_cast<uintptr_t>(elf_file_->End())) << "section is too large";
278     CHECK(shdr == &elf_file_->GetSectionHeader(elf_file_->GetSectionHeaderNum() - 1) ||
279           shdr->sh_offset + shdr->sh_size <= (shdr + 1)->sh_offset)
280         << "Section overlaps onto next section";
281     // It's mmap'd so we can just memcpy.
282     memcpy(elf_file_->Begin() + shdr->sh_offset, patches_.data(),
283            patches_.size() * sizeof(uintptr_t));
284     // TODO We should fill in the newly empty space between the last patch and
285     // the start of the next section by moving the following sections down if
286     // possible.
287     shdr->sh_size = patches_.size() * sizeof(uintptr_t);
288     return true;
289   } else {
290     LOG(ERROR) << "Unable to find section header for SHT_OAT_PATCH";
291     *error_msg_ = "Unable to find section to write patch information to in ";
292     *error_msg_ += elf_file_->GetFile().GetPath();
293     return false;
294   }
295 }
296
297 }  // namespace art