Chromium Code Reviews| 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 // Read an .android.rel.dyn ARM packed relocations section. | |
| 162 // Returns an allocated buffer holding the data, or NULL on error. | |
| 163 uint8_t* ReadArmPackedRelocs(const char* full_path, | |
| 164 off_t offset, | |
| 165 size_t bytes, | |
| 166 Error* error) { | |
| 167 uint8_t* packed_data = new uint8_t[bytes]; | |
| 168 | |
| 169 FileDescriptor fd; | |
| 170 if (!fd.OpenReadOnly(full_path)) { | |
| 171 error->Format("Error opening file '%s'", full_path); | |
| 172 delete [] packed_data; | |
| 173 return NULL; | |
| 174 } | |
| 175 if (fd.SeekTo(offset) == -1) { | |
| 176 error->Format("Error seeking to %d in file '%s'", offset, full_path); | |
| 177 delete [] packed_data; | |
| 178 return NULL; | |
| 179 } | |
| 180 const ssize_t bytes_read = fd.Read(packed_data, bytes); | |
| 181 if (bytes_read != bytes) { | |
| 182 error->Format("Error reading %d bytes from file '%s'", bytes, full_path); | |
| 183 delete [] packed_data; | |
| 184 return NULL; | |
| 185 } | |
| 186 fd.Close(); | |
| 187 | |
| 188 return packed_data; | |
| 189 } | |
| 190 | |
| 191 #endif // __arm__ | |
| 192 | |
| 151 } // namespace | 193 } // namespace |
| 152 | 194 |
| 153 SharedLibrary::SharedLibrary() { ::memset(this, 0, sizeof(*this)); } | 195 SharedLibrary::SharedLibrary() { ::memset(this, 0, sizeof(*this)); } |
| 154 | 196 |
| 155 SharedLibrary::~SharedLibrary() { | 197 SharedLibrary::~SharedLibrary() { |
| 156 // Ensure the library is unmapped on destruction. | 198 // Ensure the library is unmapped on destruction. |
| 157 if (view_.load_address()) | 199 if (view_.load_address()) |
| 158 munmap(reinterpret_cast<void*>(view_.load_address()), view_.load_size()); | 200 munmap(reinterpret_cast<void*>(view_.load_address()), view_.load_size()); |
| 201 | |
| 202 #ifdef __arm__ | |
| 203 delete [] arm_packed_relocs_; | |
|
rmcilroy
2014/06/19 10:49:44
I think you could still use your ScopedBuffer clas
simonb (inactive)
2014/06/23 14:51:32
Done.
| |
| 204 #endif | |
| 159 } | 205 } |
| 160 | 206 |
| 161 bool SharedLibrary::Load(const char* full_path, | 207 bool SharedLibrary::Load(const char* full_path, |
| 162 size_t load_address, | 208 size_t load_address, |
| 163 size_t file_offset, | 209 size_t file_offset, |
| 164 Error* error) { | 210 Error* error) { |
| 165 // First, record the path. | 211 // First, record the path. |
| 166 LOG("%s: full path '%s'\n", __FUNCTION__, full_path); | 212 LOG("%s: full path '%s'\n", __FUNCTION__, full_path); |
| 167 | 213 |
| 168 size_t full_path_len = strlen(full_path); | 214 size_t full_path_len = strlen(full_path); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 202 &relro_start_, | 248 &relro_start_, |
| 203 &relro_size_) < 0) { | 249 &relro_size_) < 0) { |
| 204 relro_start_ = 0; | 250 relro_start_ = 0; |
| 205 relro_size_ = 0; | 251 relro_size_ = 0; |
| 206 } | 252 } |
| 207 | 253 |
| 208 #ifdef __arm__ | 254 #ifdef __arm__ |
| 209 LOG("%s: Extracting ARM.exidx table for %s\n", __FUNCTION__, base_name_); | 255 LOG("%s: Extracting ARM.exidx table for %s\n", __FUNCTION__, base_name_); |
| 210 (void)phdr_table_get_arm_exidx( | 256 (void)phdr_table_get_arm_exidx( |
| 211 phdr(), phdr_count(), load_bias(), &arm_exidx_, &arm_exidx_count_); | 257 phdr(), phdr_count(), load_bias(), &arm_exidx_, &arm_exidx_count_); |
| 258 | |
| 259 off_t arm_packed_relocs_offset = 0; | |
| 260 size_t arm_packed_relocs_size = 0; | |
| 212 #endif | 261 #endif |
| 213 | 262 |
| 214 LOG("%s: Parsing dynamic table for %s\n", __FUNCTION__, base_name_); | 263 LOG("%s: Parsing dynamic table for %s\n", __FUNCTION__, base_name_); |
| 215 ElfView::DynamicIterator dyn(&view_); | 264 ElfView::DynamicIterator dyn(&view_); |
| 216 for (; dyn.HasNext(); dyn.GetNext()) { | 265 for (; dyn.HasNext(); dyn.GetNext()) { |
| 217 ELF::Addr dyn_value = dyn.GetValue(); | 266 ELF::Addr dyn_value = dyn.GetValue(); |
| 218 uintptr_t dyn_addr = dyn.GetAddress(load_bias()); | 267 uintptr_t dyn_addr = dyn.GetAddress(load_bias()); |
| 219 switch (dyn.GetTag()) { | 268 switch (dyn.GetTag()) { |
| 220 case DT_DEBUG: | 269 case DT_DEBUG: |
| 221 if (view_.dynamic_flags() & PF_W) { | 270 if (view_.dynamic_flags() & PF_W) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 262 preinit_array_count_); | 311 preinit_array_count_); |
| 263 break; | 312 break; |
| 264 case DT_SYMBOLIC: | 313 case DT_SYMBOLIC: |
| 265 LOG(" DT_SYMBOLIC\n"); | 314 LOG(" DT_SYMBOLIC\n"); |
| 266 has_DT_SYMBOLIC_ = true; | 315 has_DT_SYMBOLIC_ = true; |
| 267 break; | 316 break; |
| 268 case DT_FLAGS: | 317 case DT_FLAGS: |
| 269 if (dyn_value & DF_SYMBOLIC) | 318 if (dyn_value & DF_SYMBOLIC) |
| 270 has_DT_SYMBOLIC_ = true; | 319 has_DT_SYMBOLIC_ = true; |
| 271 break; | 320 break; |
| 321 #if defined(__arm__) | |
| 322 case DT_ANDROID_ARM_REL_OFFSET: | |
| 323 arm_packed_relocs_offset = dyn.GetOffset(); | |
| 324 LOG(" DT_ANDROID_ARM_REL_OFFSET addr=%p\n", arm_packed_relocs_offset); | |
| 325 break; | |
| 326 case DT_ANDROID_ARM_REL_SIZE: | |
| 327 arm_packed_relocs_size = dyn.GetValue(); | |
| 328 LOG(" DT_ANDROID_ARM_REL_SIZE=%d\n", arm_packed_relocs_size); | |
| 329 break; | |
| 330 #endif | |
| 272 #if defined(__mips__) | 331 #if defined(__mips__) |
| 273 case DT_MIPS_RLD_MAP: | 332 case DT_MIPS_RLD_MAP: |
| 274 *dyn.GetValuePointer() = | 333 *dyn.GetValuePointer() = |
| 275 reinterpret_cast<ELF::Addr>(Globals::GetRDebug()->GetAddress()); | 334 reinterpret_cast<ELF::Addr>(Globals::GetRDebug()->GetAddress()); |
| 276 break; | 335 break; |
| 277 #endif | 336 #endif |
| 278 default: | 337 default: |
| 279 ; | 338 ; |
| 280 } | 339 } |
| 281 } | 340 } |
| 282 | 341 |
| 342 #ifdef __arm__ | |
| 343 // If ARM packed relocations are present in the target library, read the | |
| 344 // section data and save it in arm_packed_relocs_. | |
| 345 if (arm_packed_relocs_offset && arm_packed_relocs_size) { | |
| 346 LOG("%s: ARM packed relocations found at offset %d, %d bytes\n", | |
| 347 __FUNCTION__, | |
| 348 arm_packed_relocs_offset, | |
| 349 arm_packed_relocs_size); | |
| 350 | |
| 351 arm_packed_relocs_ = | |
| 352 ReadArmPackedRelocs(full_path, | |
| 353 arm_packed_relocs_offset + file_offset, | |
| 354 arm_packed_relocs_size, | |
| 355 error); | |
| 356 if (!arm_packed_relocs_) | |
| 357 return false; | |
| 358 | |
| 359 LOG("%s: ARM packed relocations stored at %p\n", | |
| 360 __FUNCTION__, | |
| 361 arm_packed_relocs_); | |
| 362 } | |
| 363 #endif | |
| 364 | |
| 283 LOG("%s: Load complete for %s\n", __FUNCTION__, base_name_); | 365 LOG("%s: Load complete for %s\n", __FUNCTION__, base_name_); |
| 284 return true; | 366 return true; |
| 285 } | 367 } |
| 286 | 368 |
| 287 bool SharedLibrary::Relocate(LibraryList* lib_list, | 369 bool SharedLibrary::Relocate(LibraryList* lib_list, |
| 288 Vector<LibraryView*>* dependencies, | 370 Vector<LibraryView*>* dependencies, |
| 289 Error* error) { | 371 Error* error) { |
| 290 // Apply relocations. | 372 // Apply relocations. |
| 291 LOG("%s: Applying relocations to %s\n", __FUNCTION__, base_name_); | 373 LOG("%s: Applying relocations to %s\n", __FUNCTION__, base_name_); |
| 292 | 374 |
| 293 ElfRelocations relocations; | 375 ElfRelocations relocations; |
| 294 | 376 |
| 295 if (!relocations.Init(&view_, error)) | 377 if (!relocations.Init(&view_, error)) |
| 296 return false; | 378 return false; |
| 297 | 379 |
| 298 SharedLibraryResolver resolver(this, lib_list, dependencies); | 380 SharedLibraryResolver resolver(this, lib_list, dependencies); |
| 299 if (!relocations.ApplyAll(&symbols_, &resolver, error)) | 381 if (!relocations.ApplyAll(&symbols_, &resolver, error)) |
| 300 return false; | 382 return false; |
| 301 | 383 |
| 384 #ifdef __arm__ | |
| 385 // If present, also apply ARM packed relocations. | |
| 386 if (arm_packed_relocs_ && | |
| 387 !relocations.ApplyArmPackedRelocs(arm_packed_relocs_, error)) | |
| 388 return false; | |
|
rmcilroy
2014/06/19 10:49:43
I'm not sure the PackedRelocs really fits well in
simonb (inactive)
2014/06/23 14:51:32
Addressed by moving ApplyArmPackedRelocs() inside
| |
| 389 #endif | |
| 390 | |
| 302 LOG("%s: Relocations applied for %s\n", __FUNCTION__, base_name_); | 391 LOG("%s: Relocations applied for %s\n", __FUNCTION__, base_name_); |
| 303 return true; | 392 return true; |
| 304 } | 393 } |
| 305 | 394 |
| 306 const ELF::Sym* SharedLibrary::LookupSymbolEntry(const char* symbol_name) { | 395 const ELF::Sym* SharedLibrary::LookupSymbolEntry(const char* symbol_name) { |
| 307 return symbols_.LookupByName(symbol_name); | 396 return symbols_.LookupByName(symbol_name); |
| 308 } | 397 } |
| 309 | 398 |
| 310 void* SharedLibrary::FindAddressForSymbol(const char* symbol_name) { | 399 void* SharedLibrary::FindAddressForSymbol(const char* symbol_name) { |
| 311 return symbols_.LookupAddressByName(symbol_name, view_.load_bias()); | 400 return symbols_.LookupAddressByName(symbol_name, view_.load_bias()); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 441 if (iter_.GetTag() == DT_NEEDED) { | 530 if (iter_.GetTag() == DT_NEEDED) { |
| 442 dep_name_ = symbols_->GetStringById(iter_.GetValue()); | 531 dep_name_ = symbols_->GetStringById(iter_.GetValue()); |
| 443 iter_.GetNext(); | 532 iter_.GetNext(); |
| 444 return true; | 533 return true; |
| 445 } | 534 } |
| 446 } | 535 } |
| 447 return false; | 536 return false; |
| 448 } | 537 } |
| 449 | 538 |
| 450 } // namespace crazy | 539 } // namespace crazy |
| OLD | NEW |