OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "crazy_linker_shared_library.h" | 5 #include "crazy_linker_shared_library.h" |
6 | 6 |
7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
8 #include <stdlib.h> | 8 #include <stdlib.h> |
9 #include <sys/mman.h> | 9 #include <sys/mman.h> |
10 #include <elf.h> | 10 #include <elf.h> |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
51 #endif | 51 #endif |
52 | 52 |
53 #ifndef DT_PREINIT_ARRAY | 53 #ifndef DT_PREINIT_ARRAY |
54 #define DT_PREINIT_ARRAY 32 | 54 #define DT_PREINIT_ARRAY 32 |
55 #endif | 55 #endif |
56 | 56 |
57 #ifndef DT_PREINIT_ARRAYSZ | 57 #ifndef DT_PREINIT_ARRAYSZ |
58 #define DT_PREINIT_ARRAYSZ 33 | 58 #define DT_PREINIT_ARRAYSZ 33 |
59 #endif | 59 #endif |
60 | 60 |
61 // Processor-specific extension dynamic tags for packed relocations. | |
62 #ifdef __arm__ | |
63 | |
64 #define DT_ANDROID_ARM_REL_OFFSET (DT_LOPROC) | |
65 #define DT_ANDROID_ARM_REL_SIZE (DT_LOPROC + 1) | |
66 | |
67 #endif // __arm__ | |
68 | |
61 namespace crazy { | 69 namespace crazy { |
62 | 70 |
63 namespace { | 71 namespace { |
64 | 72 |
65 typedef SharedLibrary::linker_function_t linker_function_t; | 73 typedef SharedLibrary::linker_function_t linker_function_t; |
66 typedef int (*JNI_OnLoadFunctionPtr)(void* vm, void* reserved); | 74 typedef int (*JNI_OnLoadFunctionPtr)(void* vm, void* reserved); |
67 typedef void (*JNI_OnUnloadFunctionPtr)(void* vm, void* reserved); | 75 typedef void (*JNI_OnUnloadFunctionPtr)(void* vm, void* reserved); |
68 | 76 |
69 // Call a constructor or destructor function pointer. Ignore | 77 // Call a constructor or destructor function pointer. Ignore |
70 // NULL and -1 values intentionally. They correspond to markers | 78 // NULL and -1 values intentionally. They correspond to markers |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
141 | 149 |
142 // Nothing found here. | 150 // Nothing found here. |
143 return NULL; | 151 return NULL; |
144 } | 152 } |
145 | 153 |
146 private: | 154 private: |
147 SharedLibrary* lib_; | 155 SharedLibrary* lib_; |
148 Vector<LibraryView*>* dependencies_; | 156 Vector<LibraryView*>* dependencies_; |
149 }; | 157 }; |
150 | 158 |
159 #ifdef __arm__ | |
160 | |
161 // Helper class to provide a simple scoped buffer. ScopedPtr is not | |
162 // usable here because it calls delete, not delete []. | |
163 class ScopedBuffer { | |
164 public: | |
165 explicit ScopedBuffer(size_t bytes) : buffer_(new uint8_t[bytes]) { } | |
166 ~ScopedBuffer() { delete [] buffer_; } | |
167 | |
168 uint8_t* Get() { return buffer_; } | |
169 | |
170 uint8_t* Release() { | |
171 uint8_t* ptr = buffer_; | |
172 buffer_ = NULL; | |
173 return ptr; | |
174 } | |
175 | |
176 private: | |
177 uint8_t* buffer_; | |
178 }; | |
179 | |
180 // Read an .android.rel.dyn ARM packed relocations section. | |
181 // Returns an allocated buffer holding the data, or NULL on error. | |
182 uint8_t* ReadArmPackedRelocs(const char* full_path, | |
183 off_t offset, | |
184 size_t bytes, | |
185 Error* error) { | |
186 FileDescriptor fd; | |
187 if (!fd.OpenReadOnly(full_path)) { | |
188 error->Format("Error opening file '%s'", full_path); | |
189 return NULL; | |
190 } | |
191 if (fd.SeekTo(offset) == -1) { | |
192 error->Format("Error seeking to %d in file '%s'", offset, full_path); | |
193 return NULL; | |
rmcilroy
2014/06/24 09:47:22
close(fd)
simonb (inactive)
2014/06/24 11:43:55
Not needed. FileDescriptor is scoped (calls Close
| |
194 } | |
195 | |
196 ScopedBuffer buffer(bytes); | |
197 const ssize_t bytes_read = fd.Read(buffer.Get(), bytes); | |
198 if (bytes_read != bytes) { | |
199 error->Format("Error reading %d bytes from file '%s'", bytes, full_path); | |
200 return NULL; | |
rmcilroy
2014/06/24 09:47:22
ditto
simonb (inactive)
2014/06/24 11:43:55
Ditto.
| |
201 } | |
202 fd.Close(); | |
203 | |
204 uint8_t* packed_data = buffer.Release(); | |
205 return packed_data; | |
rmcilroy
2014/06/24 09:47:22
nit - just "return buffer.Release();"
simonb (inactive)
2014/06/24 11:43:55
I find this more readable as it clearly documents
| |
206 } | |
207 | |
208 #endif // __arm__ | |
209 | |
151 } // namespace | 210 } // namespace |
152 | 211 |
153 SharedLibrary::SharedLibrary() { ::memset(this, 0, sizeof(*this)); } | 212 SharedLibrary::SharedLibrary() { ::memset(this, 0, sizeof(*this)); } |
154 | 213 |
155 SharedLibrary::~SharedLibrary() { | 214 SharedLibrary::~SharedLibrary() { |
156 // Ensure the library is unmapped on destruction. | 215 // Ensure the library is unmapped on destruction. |
157 if (view_.load_address()) | 216 if (view_.load_address()) |
158 munmap(reinterpret_cast<void*>(view_.load_address()), view_.load_size()); | 217 munmap(reinterpret_cast<void*>(view_.load_address()), view_.load_size()); |
218 | |
219 #ifdef __arm__ | |
220 delete [] arm_packed_relocs_; | |
rmcilroy
2014/06/24 09:47:22
nit - you could make arm_packed_relocs_ a ScopedBu
simonb (inactive)
2014/06/24 11:43:55
Not really. ScopedBuffer is designed to be stack-
| |
221 #endif | |
159 } | 222 } |
160 | 223 |
161 bool SharedLibrary::Load(const char* full_path, | 224 bool SharedLibrary::Load(const char* full_path, |
162 size_t load_address, | 225 size_t load_address, |
163 size_t file_offset, | 226 size_t file_offset, |
164 Error* error) { | 227 Error* error) { |
165 // First, record the path. | 228 // First, record the path. |
166 LOG("%s: full path '%s'\n", __FUNCTION__, full_path); | 229 LOG("%s: full path '%s'\n", __FUNCTION__, full_path); |
167 | 230 |
168 size_t full_path_len = strlen(full_path); | 231 size_t full_path_len = strlen(full_path); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
202 &relro_start_, | 265 &relro_start_, |
203 &relro_size_) < 0) { | 266 &relro_size_) < 0) { |
204 relro_start_ = 0; | 267 relro_start_ = 0; |
205 relro_size_ = 0; | 268 relro_size_ = 0; |
206 } | 269 } |
207 | 270 |
208 #ifdef __arm__ | 271 #ifdef __arm__ |
209 LOG("%s: Extracting ARM.exidx table for %s\n", __FUNCTION__, base_name_); | 272 LOG("%s: Extracting ARM.exidx table for %s\n", __FUNCTION__, base_name_); |
210 (void)phdr_table_get_arm_exidx( | 273 (void)phdr_table_get_arm_exidx( |
211 phdr(), phdr_count(), load_bias(), &arm_exidx_, &arm_exidx_count_); | 274 phdr(), phdr_count(), load_bias(), &arm_exidx_, &arm_exidx_count_); |
275 | |
276 off_t arm_packed_relocs_offset = 0; | |
277 size_t arm_packed_relocs_size = 0; | |
212 #endif | 278 #endif |
213 | 279 |
214 LOG("%s: Parsing dynamic table for %s\n", __FUNCTION__, base_name_); | 280 LOG("%s: Parsing dynamic table for %s\n", __FUNCTION__, base_name_); |
215 ElfView::DynamicIterator dyn(&view_); | 281 ElfView::DynamicIterator dyn(&view_); |
216 for (; dyn.HasNext(); dyn.GetNext()) { | 282 for (; dyn.HasNext(); dyn.GetNext()) { |
217 ELF::Addr dyn_value = dyn.GetValue(); | 283 ELF::Addr dyn_value = dyn.GetValue(); |
218 uintptr_t dyn_addr = dyn.GetAddress(load_bias()); | 284 uintptr_t dyn_addr = dyn.GetAddress(load_bias()); |
219 switch (dyn.GetTag()) { | 285 switch (dyn.GetTag()) { |
220 case DT_DEBUG: | 286 case DT_DEBUG: |
221 if (view_.dynamic_flags() & PF_W) { | 287 if (view_.dynamic_flags() & PF_W) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
262 preinit_array_count_); | 328 preinit_array_count_); |
263 break; | 329 break; |
264 case DT_SYMBOLIC: | 330 case DT_SYMBOLIC: |
265 LOG(" DT_SYMBOLIC\n"); | 331 LOG(" DT_SYMBOLIC\n"); |
266 has_DT_SYMBOLIC_ = true; | 332 has_DT_SYMBOLIC_ = true; |
267 break; | 333 break; |
268 case DT_FLAGS: | 334 case DT_FLAGS: |
269 if (dyn_value & DF_SYMBOLIC) | 335 if (dyn_value & DF_SYMBOLIC) |
270 has_DT_SYMBOLIC_ = true; | 336 has_DT_SYMBOLIC_ = true; |
271 break; | 337 break; |
338 #if defined(__arm__) | |
339 case DT_ANDROID_ARM_REL_OFFSET: | |
340 arm_packed_relocs_offset = dyn.GetOffset(); | |
341 LOG(" DT_ANDROID_ARM_REL_OFFSET addr=%p\n", arm_packed_relocs_offset); | |
342 break; | |
343 case DT_ANDROID_ARM_REL_SIZE: | |
344 arm_packed_relocs_size = dyn.GetValue(); | |
345 LOG(" DT_ANDROID_ARM_REL_SIZE=%d\n", arm_packed_relocs_size); | |
346 break; | |
347 #endif | |
272 #if defined(__mips__) | 348 #if defined(__mips__) |
273 case DT_MIPS_RLD_MAP: | 349 case DT_MIPS_RLD_MAP: |
274 *dyn.GetValuePointer() = | 350 *dyn.GetValuePointer() = |
275 reinterpret_cast<ELF::Addr>(Globals::GetRDebug()->GetAddress()); | 351 reinterpret_cast<ELF::Addr>(Globals::GetRDebug()->GetAddress()); |
276 break; | 352 break; |
277 #endif | 353 #endif |
278 default: | 354 default: |
279 ; | 355 ; |
280 } | 356 } |
281 } | 357 } |
282 | 358 |
359 #ifdef __arm__ | |
360 // If ARM packed relocations are present in the target library, read the | |
361 // section data and save it in arm_packed_relocs_. | |
362 if (arm_packed_relocs_offset && arm_packed_relocs_size) { | |
363 LOG("%s: ARM packed relocations found at offset %d, %d bytes\n", | |
364 __FUNCTION__, | |
365 arm_packed_relocs_offset, | |
366 arm_packed_relocs_size); | |
367 | |
368 arm_packed_relocs_ = | |
369 ReadArmPackedRelocs(full_path, | |
370 arm_packed_relocs_offset + file_offset, | |
371 arm_packed_relocs_size, | |
372 error); | |
373 if (!arm_packed_relocs_) | |
374 return false; | |
375 | |
376 LOG("%s: ARM packed relocations stored at %p\n", | |
377 __FUNCTION__, | |
378 arm_packed_relocs_); | |
379 } | |
380 #endif | |
381 | |
283 LOG("%s: Load complete for %s\n", __FUNCTION__, base_name_); | 382 LOG("%s: Load complete for %s\n", __FUNCTION__, base_name_); |
284 return true; | 383 return true; |
285 } | 384 } |
286 | 385 |
287 bool SharedLibrary::Relocate(LibraryList* lib_list, | 386 bool SharedLibrary::Relocate(LibraryList* lib_list, |
288 Vector<LibraryView*>* dependencies, | 387 Vector<LibraryView*>* dependencies, |
289 Error* error) { | 388 Error* error) { |
290 // Apply relocations. | 389 // Apply relocations. |
291 LOG("%s: Applying relocations to %s\n", __FUNCTION__, base_name_); | 390 LOG("%s: Applying relocations to %s\n", __FUNCTION__, base_name_); |
292 | 391 |
293 ElfRelocations relocations; | 392 ElfRelocations relocations; |
294 | 393 |
295 if (!relocations.Init(&view_, error)) | 394 if (!relocations.Init(&view_, error)) |
296 return false; | 395 return false; |
297 | 396 |
397 #ifdef __arm__ | |
398 relocations.RegisterArmPackedRelocs(arm_packed_relocs_); | |
399 #endif | |
400 | |
298 SharedLibraryResolver resolver(this, lib_list, dependencies); | 401 SharedLibraryResolver resolver(this, lib_list, dependencies); |
299 if (!relocations.ApplyAll(&symbols_, &resolver, error)) | 402 if (!relocations.ApplyAll(&symbols_, &resolver, error)) |
300 return false; | 403 return false; |
301 | 404 |
302 LOG("%s: Relocations applied for %s\n", __FUNCTION__, base_name_); | 405 LOG("%s: Relocations applied for %s\n", __FUNCTION__, base_name_); |
303 return true; | 406 return true; |
304 } | 407 } |
305 | 408 |
306 const ELF::Sym* SharedLibrary::LookupSymbolEntry(const char* symbol_name) { | 409 const ELF::Sym* SharedLibrary::LookupSymbolEntry(const char* symbol_name) { |
307 return symbols_.LookupByName(symbol_name); | 410 return symbols_.LookupByName(symbol_name); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
441 if (iter_.GetTag() == DT_NEEDED) { | 544 if (iter_.GetTag() == DT_NEEDED) { |
442 dep_name_ = symbols_->GetStringById(iter_.GetValue()); | 545 dep_name_ = symbols_->GetStringById(iter_.GetValue()); |
443 iter_.GetNext(); | 546 iter_.GetNext(); |
444 return true; | 547 return true; |
445 } | 548 } |
446 } | 549 } |
447 return false; | 550 return false; |
448 } | 551 } |
449 | 552 |
450 } // namespace crazy | 553 } // namespace crazy |
OLD | NEW |