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 3 // found in the LICENSE file. 4 5 #include "crazy_linker_shared_library.h" 6 7 #include <dlfcn.h> 8 #include <stdlib.h> 9 #include <sys/mman.h> 10 #include <elf.h> 11 12 #include "crazy_linker_ashmem.h" 13 #include "crazy_linker_debug.h" 14 #include "crazy_linker_elf_loader.h" 15 #include "crazy_linker_elf_relocations.h" 16 #include "crazy_linker_library_list.h" 17 #include "crazy_linker_library_view.h" 18 #include "crazy_linker_globals.h" 19 #include "crazy_linker_memory_mapping.h" 20 #include "crazy_linker_thread.h" 21 #include "crazy_linker_util.h" 22 #include "crazy_linker_wrappers.h" 23 #include "linker_phdr.h" 24 25 #ifndef DF_SYMBOLIC 26 #define DF_SYMBOLIC 2 27 #endif 28 29 #ifndef DF_TEXTREL 30 #define DF_TEXTREL 4 31 #endif 32 33 #ifndef DT_INIT_ARRAY 34 #define DT_INIT_ARRAY 25 35 #endif 36 37 #ifndef DT_INIT_ARRAYSZ 38 #define DT_INIT_ARRAYSZ 27 39 #endif 40 41 #ifndef DT_FINI_ARRAY 42 #define DT_FINI_ARRAY 26 43 #endif 44 45 #ifndef DT_FINI_ARRAYSZ 46 #define DT_FINI_ARRAYSZ 28 47 #endif 48 49 #ifndef DT_FLAGS 50 #define DT_FLAGS 30 51 #endif 52 53 #ifndef DT_PREINIT_ARRAY 54 #define DT_PREINIT_ARRAY 32 55 #endif 56 57 #ifndef DT_PREINIT_ARRAYSZ 58 #define DT_PREINIT_ARRAYSZ 33 59 #endif 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 { 74 75 namespace { 76 77 typedef SharedLibrary::linker_function_t linker_function_t; 78 typedef int (*JNI_OnLoadFunctionPtr)(void* vm, void* reserved); 79 typedef void (*JNI_OnUnloadFunctionPtr)(void* vm, void* reserved); 80 81 // Call a constructor or destructor function pointer. Ignore 82 // NULL and -1 values intentionally. They correspond to markers 83 // in the tables, or deleted values. 84 // |func_type| corresponds to the type of the function, and is only 85 // used for debugging (examples are "DT_INIT", "DT_INIT_ARRAY", etc...). 86 void CallFunction(linker_function_t func, const char* func_type) { 87 uintptr_t func_address = reinterpret_cast<uintptr_t>(func); 88 89 LOG("%s: %p %s\n", __FUNCTION__, func, func_type); 90 if (func_address != 0 && func_address != uintptr_t(-1)) 91 func(); 92 } 93 94 // An instance of ElfRelocator::SymbolResolver that can be used 95 // to resolve symbols in a shared library being loaded by 96 // LibraryList::LoadLibrary. 97 class SharedLibraryResolver : public ElfRelocations::SymbolResolver { 98 public: 99 SharedLibraryResolver(SharedLibrary* lib, 100 LibraryList* lib_list, 101 Vector<LibraryView*>* dependencies) 102 : lib_(lib), dependencies_(dependencies) {} 103 104 virtual void* Lookup(const char* symbol_name) { 105 // TODO(digit): Add the ability to lookup inside the main executable. 106 107 // First, look inside the current library. 108 const ELF::Sym* entry = lib_->LookupSymbolEntry(symbol_name); 109 if (entry) 110 return reinterpret_cast<void*>(lib_->load_bias() + entry->st_value); 111 112 // Special case: redirect the dynamic linker symbols to our wrappers. 113 // This ensures that loaded libraries can call dlopen() / dlsym() 114 // and transparently use the crazy linker to perform their duty. 115 void* address = WrapLinkerSymbol(symbol_name); 116 if (address) 117 return address; 118 119 // Then look inside the dependencies. 120 for (size_t n = 0; n < dependencies_->GetCount(); ++n) { 121 LibraryView* wrap = (*dependencies_)[n]; 122 // LOG("%s: Looking into dependency %p (%s)\n", __FUNCTION__, wrap, 123 // wrap->GetName()); 124 if (wrap->IsSystem()) { 125 address = ::dlsym(wrap->GetSystem(), symbol_name); 126 #ifdef __arm__ 127 // Android libm.so defines isnanf as weak. This means that its 128 // address cannot be found by dlsym(), which always returns NULL 129 // for weak symbols. However, libm.so contains the real isnanf 130 // as __isnanf. If we encounter isnanf and fail to resolve it in 131 // libm.so, retry with __isnanf. 132 // 133 // This occurs only in clang, which lacks __builtin_isnanf. The 134 // gcc compiler implements isnanf as a builtin, so the symbol 135 // isnanf never need be resolved in gcc builds. 136 // 137 // http://code.google.com/p/chromium/issues/detail?id=376828 138 if (!address && 139 !strcmp(symbol_name, "isnanf") && 140 !strcmp(wrap->GetName(), "libm.so")) 141 address = ::dlsym(wrap->GetSystem(), "__isnanf"); 142 #endif 143 if (address) 144 return address; 145 } 146 if (wrap->IsCrazy()) { 147 SharedLibrary* dep = wrap->GetCrazy(); 148 entry = dep->LookupSymbolEntry(symbol_name); 149 if (entry) 150 return reinterpret_cast<void*>(dep->load_bias() + entry->st_value); 151 } 152 } 153 154 // Nothing found here. 155 return NULL; 156 } 157 158 private: 159 SharedLibrary* lib_; 160 Vector<LibraryView*>* dependencies_; 161 }; 162 163 #if defined(__arm__) || defined(__aarch64__) 164 165 // Helper class to provide a simple scoped buffer. ScopedPtr is not 166 // usable here because it calls delete, not delete []. 167 class ScopedBuffer { 168 public: 169 explicit ScopedBuffer(size_t bytes) : buffer_(new uint8_t[bytes]) { } 170 ~ScopedBuffer() { delete [] buffer_; } 171 172 uint8_t* Get() { return buffer_; } 173 174 uint8_t* Release() { 175 uint8_t* ptr = buffer_; 176 buffer_ = NULL; 177 return ptr; 178 } 179 180 private: 181 uint8_t* buffer_; 182 }; 183 184 // Read an .android.rel.dyn packed relocations section. 185 // Returns an allocated buffer holding the data, or NULL on error. 186 uint8_t* ReadPackedRelocations(const char* full_path, 187 off_t offset, 188 size_t bytes, 189 Error* error) { 190 FileDescriptor fd; 191 if (!fd.OpenReadOnly(full_path)) { 192 error->Format("Error opening file '%s'", full_path); 193 return NULL; 194 } 195 if (fd.SeekTo(offset) == -1) { 196 error->Format("Error seeking to %d in file '%s'", offset, full_path); 197 return NULL; 198 } 199 200 ScopedBuffer buffer(bytes); 201 const ssize_t bytes_read = fd.Read(buffer.Get(), bytes); 202 if (static_cast<size_t>(bytes_read) != bytes) { 203 error->Format("Error reading %d bytes from file '%s'", bytes, full_path); 204 return NULL; 205 } 206 fd.Close(); 207 208 uint8_t* packed_data = buffer.Release(); 209 return packed_data; 210 } 211 212 #endif // __arm__ || __aarch64__ 213 214 } // namespace 215 216 SharedLibrary::SharedLibrary() { ::memset(this, 0, sizeof(*this)); } 217 218 SharedLibrary::~SharedLibrary() { 219 // Ensure the library is unmapped on destruction. 220 if (view_.load_address()) 221 munmap(reinterpret_cast<void*>(view_.load_address()), view_.load_size()); 222 223 #if defined(__arm__) || defined(__aarch64__) 224 delete [] packed_relocations_; 225 #endif 226 } 227 228 bool SharedLibrary::Load(const char* full_path, 229 size_t load_address, 230 size_t file_offset, 231 Error* error) { 232 // First, record the path. 233 LOG("%s: full path '%s'\n", __FUNCTION__, full_path); 234 235 size_t full_path_len = strlen(full_path); 236 if (full_path_len >= sizeof(full_path_)) { 237 error->Format("Path too long: %s", full_path); 238 return false; 239 } 240 241 strlcpy(full_path_, full_path, sizeof(full_path_)); 242 base_name_ = GetBaseNamePtr(full_path_); 243 244 // Load the ELF binary in memory. 245 LOG("%s: Loading ELF segments for %s\n", __FUNCTION__, base_name_); 246 247 { 248 ElfLoader loader; 249 if (!loader.LoadAt(full_path_, file_offset, load_address, error)) { 250 return false; 251 } 252 253 if (!view_.InitUnmapped(loader.load_start(), 254 loader.loaded_phdr(), 255 loader.phdr_count(), 256 error)) { 257 return false; 258 } 259 260 if (!symbols_.Init(&view_)) { 261 *error = "Missing or malformed symbol table"; 262 return false; 263 } 264 } 265 266 if (phdr_table_get_relro_info(view_.phdr(), 267 view_.phdr_count(), 268 view_.load_bias(), 269 &relro_start_, 270 &relro_size_) < 0) { 271 relro_start_ = 0; 272 relro_size_ = 0; 273 } 274 275 #ifdef __arm__ 276 LOG("%s: Extracting ARM.exidx table for %s\n", __FUNCTION__, base_name_); 277 (void)phdr_table_get_arm_exidx( 278 phdr(), phdr_count(), load_bias(), &arm_exidx_, &arm_exidx_count_); 279 #endif 280 281 #if defined(__arm__) || defined(__aarch64__) 282 off_t packed_relocations_offset = 0; 283 size_t packed_relocations_size = 0; 284 #endif 285 286 LOG("%s: Parsing dynamic table for %s\n", __FUNCTION__, base_name_); 287 ElfView::DynamicIterator dyn(&view_); 288 for (; dyn.HasNext(); dyn.GetNext()) { 289 ELF::Addr dyn_value = dyn.GetValue(); 290 uintptr_t dyn_addr = dyn.GetAddress(load_bias()); 291 switch (dyn.GetTag()) { 292 case DT_DEBUG: 293 if (view_.dynamic_flags() & PF_W) { 294 *dyn.GetValuePointer() = 295 reinterpret_cast<uintptr_t>(Globals::GetRDebug()->GetAddress()); 296 } 297 break; 298 case DT_INIT: 299 LOG(" DT_INIT addr=%p\n", dyn_addr); 300 init_func_ = reinterpret_cast<linker_function_t>(dyn_addr); 301 break; 302 case DT_FINI: 303 LOG(" DT_FINI addr=%p\n", dyn_addr); 304 fini_func_ = reinterpret_cast<linker_function_t>(dyn_addr); 305 break; 306 case DT_INIT_ARRAY: 307 LOG(" DT_INIT_ARRAY addr=%p\n", dyn_addr); 308 init_array_ = reinterpret_cast<linker_function_t*>(dyn_addr); 309 break; 310 case DT_INIT_ARRAYSZ: 311 init_array_count_ = dyn_value / sizeof(ELF::Addr); 312 LOG(" DT_INIT_ARRAYSZ value=%p count=%p\n", 313 dyn_value, 314 init_array_count_); 315 break; 316 case DT_FINI_ARRAY: 317 LOG(" DT_FINI_ARRAY addr=%p\n", dyn_addr); 318 fini_array_ = reinterpret_cast<linker_function_t*>(dyn_addr); 319 break; 320 case DT_FINI_ARRAYSZ: 321 fini_array_count_ = dyn_value / sizeof(ELF::Addr); 322 LOG(" DT_FINI_ARRAYSZ value=%p count=%p\n", 323 dyn_value, 324 fini_array_count_); 325 break; 326 case DT_PREINIT_ARRAY: 327 LOG(" DT_PREINIT_ARRAY addr=%p\n", dyn_addr); 328 preinit_array_ = reinterpret_cast<linker_function_t*>(dyn_addr); 329 break; 330 case DT_PREINIT_ARRAYSZ: 331 preinit_array_count_ = dyn_value / sizeof(ELF::Addr); 332 LOG(" DT_PREINIT_ARRAYSZ value=%p count=%p\n", 333 dyn_value, 334 preinit_array_count_); 335 break; 336 case DT_SYMBOLIC: 337 LOG(" DT_SYMBOLIC\n"); 338 has_DT_SYMBOLIC_ = true; 339 break; 340 case DT_FLAGS: 341 if (dyn_value & DF_SYMBOLIC) 342 has_DT_SYMBOLIC_ = true; 343 break; 344 #if defined(__arm__) || defined(__aarch64__) 345 case DT_ANDROID_REL_OFFSET: 346 packed_relocations_offset = dyn.GetOffset(); 347 LOG(" DT_ANDROID_REL_OFFSET addr=%p\n", packed_relocations_offset); 348 break; 349 case DT_ANDROID_REL_SIZE: 350 packed_relocations_size = dyn.GetValue(); 351 LOG(" DT_ANDROID_REL_SIZE=%d\n", packed_relocations_size); 352 break; 353 #endif 354 #if defined(__mips__) 355 case DT_MIPS_RLD_MAP: 356 *dyn.GetValuePointer() = 357 reinterpret_cast<ELF::Addr>(Globals::GetRDebug()->GetAddress()); 358 break; 359 #endif 360 default: 361 ; 362 } 363 } 364 365 #if defined(__arm__) || defined(__aarch64__) 366 // If packed relocations are present in the target library, read the 367 // section data and save it in packed_relocations_. 368 if (packed_relocations_offset && packed_relocations_size) { 369 LOG("%s: Packed relocations found at offset %d, %d bytes\n", 370 __FUNCTION__, 371 packed_relocations_offset, 372 packed_relocations_size); 373 374 packed_relocations_ = 375 ReadPackedRelocations(full_path, 376 packed_relocations_offset + file_offset, 377 packed_relocations_size, 378 error); 379 if (!packed_relocations_) 380 return false; 381 382 LOG("%s: Packed relocations stored at %p\n", 383 __FUNCTION__, 384 packed_relocations_); 385 } 386 #endif 387 388 LOG("%s: Load complete for %s\n", __FUNCTION__, base_name_); 389 return true; 390 } 391 392 bool SharedLibrary::Relocate(LibraryList* lib_list, 393 Vector<LibraryView*>* dependencies, 394 Error* error) { 395 // Apply relocations. 396 LOG("%s: Applying relocations to %s\n", __FUNCTION__, base_name_); 397 398 ElfRelocations relocations; 399 400 if (!relocations.Init(&view_, error)) 401 return false; 402 403 #if defined(__arm__) || defined(__aarch64__) 404 relocations.RegisterPackedRelocations(packed_relocations_); 405 #endif 406 407 SharedLibraryResolver resolver(this, lib_list, dependencies); 408 if (!relocations.ApplyAll(&symbols_, &resolver, error)) 409 return false; 410 411 LOG("%s: Relocations applied for %s\n", __FUNCTION__, base_name_); 412 return true; 413 } 414 415 const ELF::Sym* SharedLibrary::LookupSymbolEntry(const char* symbol_name) { 416 return symbols_.LookupByName(symbol_name); 417 } 418 419 void* SharedLibrary::FindAddressForSymbol(const char* symbol_name) { 420 return symbols_.LookupAddressByName(symbol_name, view_.load_bias()); 421 } 422 423 bool SharedLibrary::CreateSharedRelro(size_t load_address, 424 size_t* relro_start, 425 size_t* relro_size, 426 int* relro_fd, 427 Error* error) { 428 SharedRelro relro; 429 430 if (!relro.Allocate(relro_size_, base_name_, error)) 431 return false; 432 433 if (load_address != 0 && load_address != this->load_address()) { 434 // Need to relocate the content of the ashmem region first to accomodate 435 // for the new load address. 436 if (!relro.CopyFromRelocated( 437 &view_, load_address, relro_start_, relro_size_, error)) 438 return false; 439 } else { 440 // Simply copy, no relocations. 441 if (!relro.CopyFrom(relro_start_, relro_size_, error)) 442 return false; 443 } 444 445 // Enforce read-only mode for the region's content. 446 if (!relro.ForceReadOnly(error)) 447 return false; 448 449 // All good. 450 *relro_start = relro.start(); 451 *relro_size = relro.size(); 452 *relro_fd = relro.DetachFd(); 453 return true; 454 } 455 456 bool SharedLibrary::UseSharedRelro(size_t relro_start, 457 size_t relro_size, 458 int relro_fd, 459 Error* error) { 460 LOG("%s: relro_start=%p relro_size=%p relro_fd=%d\n", 461 __FUNCTION__, 462 (void*)relro_start, 463 (void*)relro_size, 464 relro_fd); 465 466 if (relro_fd < 0 || relro_size == 0) { 467 // Nothing to do here. 468 return true; 469 } 470 471 // Sanity check: A shared RELRO is not already used. 472 if (relro_used_) { 473 *error = "Library already using shared RELRO section"; 474 return false; 475 } 476 477 // Sanity check: RELRO addresses must match. 478 if (relro_start_ != relro_start || relro_size_ != relro_size) { 479 error->Format("RELRO mismatch addr=%p size=%p (wanted addr=%p size=%p)", 480 relro_start_, 481 relro_size_, 482 relro_start, 483 relro_size); 484 return false; 485 } 486 487 // Everything's good, swap pages in this process's address space. 488 SharedRelro relro; 489 if (!relro.InitFrom(relro_start, relro_size, relro_fd, error)) 490 return false; 491 492 relro_used_ = true; 493 return true; 494 } 495 496 void SharedLibrary::CallConstructors() { 497 CallFunction(init_func_, "DT_INIT"); 498 for (size_t n = 0; n < init_array_count_; ++n) 499 CallFunction(init_array_[n], "DT_INIT_ARRAY"); 500 } 501 502 void SharedLibrary::CallDestructors() { 503 for (size_t n = fini_array_count_; n > 0; --n) { 504 CallFunction(fini_array_[n - 1], "DT_FINI_ARRAY"); 505 } 506 CallFunction(fini_func_, "DT_FINI"); 507 } 508 509 bool SharedLibrary::SetJavaVM(void* java_vm, 510 int minimum_jni_version, 511 Error* error) { 512 if (java_vm == NULL) 513 return true; 514 515 // Lookup for JNI_OnLoad, exit if it doesn't exist. 516 JNI_OnLoadFunctionPtr jni_onload = reinterpret_cast<JNI_OnLoadFunctionPtr>( 517 FindAddressForSymbol("JNI_OnLoad")); 518 if (!jni_onload) 519 return true; 520 521 int jni_version = (*jni_onload)(java_vm, NULL); 522 if (jni_version < minimum_jni_version) { 523 error->Format("JNI_OnLoad() in %s returned %d, expected at least %d", 524 full_path_, 525 jni_version, 526 minimum_jni_version); 527 return false; 528 } 529 530 // Save the JavaVM handle for unload time. 531 java_vm_ = java_vm; 532 return true; 533 } 534 535 void SharedLibrary::CallJniOnUnload() { 536 if (!java_vm_) 537 return; 538 539 JNI_OnUnloadFunctionPtr jni_on_unload = 540 reinterpret_cast<JNI_OnUnloadFunctionPtr>( 541 this->FindAddressForSymbol("JNI_OnUnload")); 542 543 if (jni_on_unload) 544 (*jni_on_unload)(java_vm_, NULL); 545 } 546 547 bool SharedLibrary::DependencyIterator::GetNext() { 548 dep_name_ = NULL; 549 for (; iter_.HasNext(); iter_.GetNext()) { 550 if (iter_.GetTag() == DT_NEEDED) { 551 dep_name_ = symbols_->GetStringById(iter_.GetValue()); 552 iter_.GetNext(); 553 return true; 554 } 555 } 556 return false; 557 } 558 559 } // namespace crazy 560