| 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 #ifndef DT_LOOS | |
| 62 #define DT_LOOS 0x6000000d | |
| 63 #endif | |
| 64 | |
| 65 // Extension dynamic tags for packed relocations. | |
| 66 #if defined(__arm__) || defined(__aarch64__) | |
| 67 | |
| 68 #define DT_ANDROID_REL_OFFSET (DT_LOOS) | |
| 69 #define DT_ANDROID_REL_SIZE (DT_LOOS + 1) | |
| 70 | |
| 71 #endif // __arm__ || __aarch64__ | |
| 72 | |
| 73 namespace crazy { | 61 namespace crazy { |
| 74 | 62 |
| 75 namespace { | 63 namespace { |
| 76 | 64 |
| 77 typedef SharedLibrary::linker_function_t linker_function_t; | 65 typedef SharedLibrary::linker_function_t linker_function_t; |
| 78 typedef int (*JNI_OnLoadFunctionPtr)(void* vm, void* reserved); | 66 typedef int (*JNI_OnLoadFunctionPtr)(void* vm, void* reserved); |
| 79 typedef void (*JNI_OnUnloadFunctionPtr)(void* vm, void* reserved); | 67 typedef void (*JNI_OnUnloadFunctionPtr)(void* vm, void* reserved); |
| 80 | 68 |
| 81 // Call a constructor or destructor function pointer. Ignore | 69 // Call a constructor or destructor function pointer. Ignore |
| 82 // NULL and -1 values intentionally. They correspond to markers | 70 // NULL and -1 values intentionally. They correspond to markers |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 | 175 |
| 188 return NULL; | 176 return NULL; |
| 189 } | 177 } |
| 190 | 178 |
| 191 void* main_program_handle_; | 179 void* main_program_handle_; |
| 192 SharedLibrary* lib_; | 180 SharedLibrary* lib_; |
| 193 Vector<LibraryView*>* preloads_; | 181 Vector<LibraryView*>* preloads_; |
| 194 Vector<LibraryView*>* dependencies_; | 182 Vector<LibraryView*>* dependencies_; |
| 195 }; | 183 }; |
| 196 | 184 |
| 197 #if defined(__arm__) || defined(__aarch64__) | |
| 198 | |
| 199 // Helper class to provide a simple scoped buffer. ScopedPtr is not | |
| 200 // usable here because it calls delete, not delete []. | |
| 201 class ScopedBuffer { | |
| 202 public: | |
| 203 explicit ScopedBuffer(size_t bytes) : buffer_(new uint8_t[bytes]) { } | |
| 204 ~ScopedBuffer() { delete [] buffer_; } | |
| 205 | |
| 206 uint8_t* Get() { return buffer_; } | |
| 207 | |
| 208 uint8_t* Release() { | |
| 209 uint8_t* ptr = buffer_; | |
| 210 buffer_ = NULL; | |
| 211 return ptr; | |
| 212 } | |
| 213 | |
| 214 private: | |
| 215 uint8_t* buffer_; | |
| 216 }; | |
| 217 | |
| 218 // Read an .android.rel.dyn packed relocations section. | |
| 219 // Returns an allocated buffer holding the data, or NULL on error. | |
| 220 uint8_t* ReadPackedRelocations(const char* full_path, | |
| 221 off_t offset, | |
| 222 size_t bytes, | |
| 223 Error* error) { | |
| 224 FileDescriptor fd; | |
| 225 if (!fd.OpenReadOnly(full_path)) { | |
| 226 error->Format("Error opening file '%s'", full_path); | |
| 227 return NULL; | |
| 228 } | |
| 229 if (fd.SeekTo(offset) == -1) { | |
| 230 error->Format("Error seeking to %d in file '%s'", offset, full_path); | |
| 231 return NULL; | |
| 232 } | |
| 233 | |
| 234 ScopedBuffer buffer(bytes); | |
| 235 const ssize_t bytes_read = fd.Read(buffer.Get(), bytes); | |
| 236 if (static_cast<size_t>(bytes_read) != bytes) { | |
| 237 error->Format("Error reading %d bytes from file '%s'", bytes, full_path); | |
| 238 return NULL; | |
| 239 } | |
| 240 fd.Close(); | |
| 241 | |
| 242 uint8_t* packed_data = buffer.Release(); | |
| 243 return packed_data; | |
| 244 } | |
| 245 | |
| 246 #endif // __arm__ || __aarch64__ | |
| 247 | |
| 248 } // namespace | 185 } // namespace |
| 249 | 186 |
| 250 SharedLibrary::SharedLibrary() { ::memset(this, 0, sizeof(*this)); } | 187 SharedLibrary::SharedLibrary() { ::memset(this, 0, sizeof(*this)); } |
| 251 | 188 |
| 252 SharedLibrary::~SharedLibrary() { | 189 SharedLibrary::~SharedLibrary() { |
| 253 // Ensure the library is unmapped on destruction. | 190 // Ensure the library is unmapped on destruction. |
| 254 if (view_.load_address()) | 191 if (view_.load_address()) |
| 255 munmap(reinterpret_cast<void*>(view_.load_address()), view_.load_size()); | 192 munmap(reinterpret_cast<void*>(view_.load_address()), view_.load_size()); |
| 256 | |
| 257 #if defined(__arm__) || defined(__aarch64__) | |
| 258 delete [] packed_relocations_; | |
| 259 #endif | |
| 260 } | 193 } |
| 261 | 194 |
| 262 bool SharedLibrary::Load(const char* full_path, | 195 bool SharedLibrary::Load(const char* full_path, |
| 263 size_t load_address, | 196 size_t load_address, |
| 264 size_t file_offset, | 197 size_t file_offset, |
| 265 Error* error) { | 198 Error* error) { |
| 266 // First, record the path. | 199 // First, record the path. |
| 267 LOG("%s: full path '%s'\n", __FUNCTION__, full_path); | 200 LOG("%s: full path '%s'\n", __FUNCTION__, full_path); |
| 268 | 201 |
| 269 size_t full_path_len = strlen(full_path); | 202 size_t full_path_len = strlen(full_path); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 relro_start_ = 0; | 238 relro_start_ = 0; |
| 306 relro_size_ = 0; | 239 relro_size_ = 0; |
| 307 } | 240 } |
| 308 | 241 |
| 309 #ifdef __arm__ | 242 #ifdef __arm__ |
| 310 LOG("%s: Extracting ARM.exidx table for %s\n", __FUNCTION__, base_name_); | 243 LOG("%s: Extracting ARM.exidx table for %s\n", __FUNCTION__, base_name_); |
| 311 (void)phdr_table_get_arm_exidx( | 244 (void)phdr_table_get_arm_exidx( |
| 312 phdr(), phdr_count(), load_bias(), &arm_exidx_, &arm_exidx_count_); | 245 phdr(), phdr_count(), load_bias(), &arm_exidx_, &arm_exidx_count_); |
| 313 #endif | 246 #endif |
| 314 | 247 |
| 315 #if defined(__arm__) || defined(__aarch64__) | |
| 316 off_t packed_relocations_offset = 0; | |
| 317 size_t packed_relocations_size = 0; | |
| 318 #endif | |
| 319 | |
| 320 LOG("%s: Parsing dynamic table for %s\n", __FUNCTION__, base_name_); | 248 LOG("%s: Parsing dynamic table for %s\n", __FUNCTION__, base_name_); |
| 321 ElfView::DynamicIterator dyn(&view_); | 249 ElfView::DynamicIterator dyn(&view_); |
| 322 for (; dyn.HasNext(); dyn.GetNext()) { | 250 for (; dyn.HasNext(); dyn.GetNext()) { |
| 323 ELF::Addr dyn_value = dyn.GetValue(); | 251 ELF::Addr dyn_value = dyn.GetValue(); |
| 324 uintptr_t dyn_addr = dyn.GetAddress(load_bias()); | 252 uintptr_t dyn_addr = dyn.GetAddress(load_bias()); |
| 325 switch (dyn.GetTag()) { | 253 switch (dyn.GetTag()) { |
| 326 case DT_DEBUG: | 254 case DT_DEBUG: |
| 327 if (view_.dynamic_flags() & PF_W) { | 255 if (view_.dynamic_flags() & PF_W) { |
| 328 *dyn.GetValuePointer() = | 256 *dyn.GetValuePointer() = |
| 329 reinterpret_cast<uintptr_t>(Globals::GetRDebug()->GetAddress()); | 257 reinterpret_cast<uintptr_t>(Globals::GetRDebug()->GetAddress()); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 preinit_array_count_); | 296 preinit_array_count_); |
| 369 break; | 297 break; |
| 370 case DT_SYMBOLIC: | 298 case DT_SYMBOLIC: |
| 371 LOG(" DT_SYMBOLIC\n"); | 299 LOG(" DT_SYMBOLIC\n"); |
| 372 has_DT_SYMBOLIC_ = true; | 300 has_DT_SYMBOLIC_ = true; |
| 373 break; | 301 break; |
| 374 case DT_FLAGS: | 302 case DT_FLAGS: |
| 375 if (dyn_value & DF_SYMBOLIC) | 303 if (dyn_value & DF_SYMBOLIC) |
| 376 has_DT_SYMBOLIC_ = true; | 304 has_DT_SYMBOLIC_ = true; |
| 377 break; | 305 break; |
| 378 #if defined(__arm__) || defined(__aarch64__) | |
| 379 case DT_ANDROID_REL_OFFSET: | |
| 380 packed_relocations_offset = dyn.GetOffset(); | |
| 381 LOG(" DT_ANDROID_REL_OFFSET addr=%p\n", packed_relocations_offset); | |
| 382 break; | |
| 383 case DT_ANDROID_REL_SIZE: | |
| 384 packed_relocations_size = dyn.GetValue(); | |
| 385 LOG(" DT_ANDROID_REL_SIZE=%d\n", packed_relocations_size); | |
| 386 break; | |
| 387 #endif | |
| 388 #if defined(__mips__) | 306 #if defined(__mips__) |
| 389 case DT_MIPS_RLD_MAP: | 307 case DT_MIPS_RLD_MAP: |
| 390 *dyn.GetValuePointer() = | 308 *dyn.GetValuePointer() = |
| 391 reinterpret_cast<ELF::Addr>(Globals::GetRDebug()->GetAddress()); | 309 reinterpret_cast<ELF::Addr>(Globals::GetRDebug()->GetAddress()); |
| 392 break; | 310 break; |
| 393 #endif | 311 #endif |
| 394 default: | 312 default: |
| 395 ; | 313 ; |
| 396 } | 314 } |
| 397 } | 315 } |
| 398 | 316 |
| 399 #if defined(__arm__) || defined(__aarch64__) | |
| 400 // If packed relocations are present in the target library, read the | |
| 401 // section data and save it in packed_relocations_. | |
| 402 if (packed_relocations_offset && packed_relocations_size) { | |
| 403 LOG("%s: Packed relocations found at offset %d, %d bytes\n", | |
| 404 __FUNCTION__, | |
| 405 packed_relocations_offset, | |
| 406 packed_relocations_size); | |
| 407 | |
| 408 packed_relocations_ = | |
| 409 ReadPackedRelocations(full_path, | |
| 410 packed_relocations_offset + file_offset, | |
| 411 packed_relocations_size, | |
| 412 error); | |
| 413 if (!packed_relocations_) | |
| 414 return false; | |
| 415 | |
| 416 LOG("%s: Packed relocations stored at %p\n", | |
| 417 __FUNCTION__, | |
| 418 packed_relocations_); | |
| 419 | |
| 420 // Add packed relocations to the view. | |
| 421 view_.RegisterPackedRelocations(packed_relocations_); | |
| 422 } | |
| 423 #endif | |
| 424 | |
| 425 LOG("%s: Load complete for %s\n", __FUNCTION__, base_name_); | 317 LOG("%s: Load complete for %s\n", __FUNCTION__, base_name_); |
| 426 return true; | 318 return true; |
| 427 } | 319 } |
| 428 | 320 |
| 429 bool SharedLibrary::Relocate(LibraryList* lib_list, | 321 bool SharedLibrary::Relocate(LibraryList* lib_list, |
| 430 Vector<LibraryView*>* preloads, | 322 Vector<LibraryView*>* preloads, |
| 431 Vector<LibraryView*>* dependencies, | 323 Vector<LibraryView*>* dependencies, |
| 432 Error* error) { | 324 Error* error) { |
| 433 // Apply relocations. | 325 // Apply relocations. |
| 434 LOG("%s: Applying relocations to %s\n", __FUNCTION__, base_name_); | 326 LOG("%s: Applying relocations to %s\n", __FUNCTION__, base_name_); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 584 if (iter_.GetTag() == DT_NEEDED) { | 476 if (iter_.GetTag() == DT_NEEDED) { |
| 585 dep_name_ = symbols_->GetStringById(iter_.GetValue()); | 477 dep_name_ = symbols_->GetStringById(iter_.GetValue()); |
| 586 iter_.GetNext(); | 478 iter_.GetNext(); |
| 587 return true; | 479 return true; |
| 588 } | 480 } |
| 589 } | 481 } |
| 590 return false; | 482 return false; |
| 591 } | 483 } |
| 592 | 484 |
| 593 } // namespace crazy | 485 } // namespace crazy |
| OLD | NEW |