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