| 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_elf_relocations.h" | 5 #include "crazy_linker_elf_relocations.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 | 8 |
| 9 #include "crazy_linker_debug.h" | 9 #include "crazy_linker_debug.h" |
| 10 #include "crazy_linker_elf_symbols.h" | 10 #include "crazy_linker_elf_symbols.h" |
| 11 #include "crazy_linker_elf_view.h" | 11 #include "crazy_linker_elf_view.h" |
| 12 #include "crazy_linker_error.h" | 12 #include "crazy_linker_error.h" |
| 13 #include "crazy_linker_system.h" |
| 13 #include "crazy_linker_util.h" | 14 #include "crazy_linker_util.h" |
| 14 #include "linker_phdr.h" | 15 #include "linker_phdr.h" |
| 15 | 16 |
| 16 #define DEBUG_RELOCATIONS 0 | 17 #define DEBUG_RELOCATIONS 0 |
| 17 | 18 |
| 18 #define RLOG(...) LOG_IF(DEBUG_RELOCATIONS, __VA_ARGS__) | 19 #define RLOG(...) LOG_IF(DEBUG_RELOCATIONS, __VA_ARGS__) |
| 19 #define RLOG_ERRNO(...) LOG_ERRNO_IF(DEBUG_RELOCATIONS, __VA_ARGS__) | 20 #define RLOG_ERRNO(...) LOG_ERRNO_IF(DEBUG_RELOCATIONS, __VA_ARGS__) |
| 20 | 21 |
| 21 #ifndef DF_SYMBOLIC | 22 #ifndef DF_SYMBOLIC |
| 22 #define DF_SYMBOLIC 2 | 23 #define DF_SYMBOLIC 2 |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 error)) | 280 error)) |
| 280 return false; | 281 return false; |
| 281 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(relocations_), | 282 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(relocations_), |
| 282 relocations_size_ / sizeof(ELF::Rel), | 283 relocations_size_ / sizeof(ELF::Rel), |
| 283 symbols, | 284 symbols, |
| 284 resolver, | 285 resolver, |
| 285 error)) | 286 error)) |
| 286 return false; | 287 return false; |
| 287 } | 288 } |
| 288 | 289 |
| 289 else if (relocations_type_ == DT_RELA) { | 290 if (relocations_type_ == DT_RELA) { |
| 290 if (!ApplyRelaRelocs(reinterpret_cast<ELF::Rela*>(plt_relocations_), | 291 if (!ApplyRelaRelocs(reinterpret_cast<ELF::Rela*>(plt_relocations_), |
| 291 plt_relocations_size_ / sizeof(ELF::Rela), | 292 plt_relocations_size_ / sizeof(ELF::Rela), |
| 292 symbols, | 293 symbols, |
| 293 resolver, | 294 resolver, |
| 294 error)) | 295 error)) |
| 295 return false; | 296 return false; |
| 296 if (!ApplyRelaRelocs(reinterpret_cast<ELF::Rela*>(relocations_), | 297 if (!ApplyRelaRelocs(reinterpret_cast<ELF::Rela*>(relocations_), |
| 297 relocations_size_ / sizeof(ELF::Rela), | 298 relocations_size_ / sizeof(ELF::Rela), |
| 298 symbols, | 299 symbols, |
| 299 resolver, | 300 resolver, |
| 300 error)) | 301 error)) |
| 301 return false; | 302 return false; |
| 302 } | 303 } |
| 303 | 304 |
| 305 #ifdef __arm__ |
| 306 if (!ApplyArmPackedRelocs(error)) |
| 307 return false; |
| 308 #endif |
| 309 |
| 304 #ifdef __mips__ | 310 #ifdef __mips__ |
| 305 if (!RelocateMipsGot(symbols, resolver, error)) | 311 if (!RelocateMipsGot(symbols, resolver, error)) |
| 306 return false; | 312 return false; |
| 307 #endif | 313 #endif |
| 308 | 314 |
| 309 if (has_text_relocations_) { | 315 if (has_text_relocations_) { |
| 310 if (phdr_table_protect_segments(phdr_, phdr_count_, load_bias_) < 0) { | 316 if (phdr_table_protect_segments(phdr_, phdr_count_, load_bias_) < 0) { |
| 311 error->Format("Can't reprotect loadable segments: %s", strerror(errno)); | 317 error->Format("Can't reprotect loadable segments: %s", strerror(errno)); |
| 312 return false; | 318 return false; |
| 313 } | 319 } |
| 314 } | 320 } |
| 315 | 321 |
| 316 LOG("%s: Done\n", __FUNCTION__); | 322 LOG("%s: Done\n", __FUNCTION__); |
| 317 return true; | 323 return true; |
| 318 } | 324 } |
| 319 | 325 |
| 326 #ifdef __arm__ |
| 327 |
| 328 void ElfRelocations::RegisterArmPackedRelocs(uint8_t* arm_packed_relocs) { |
| 329 arm_packed_relocs_ = arm_packed_relocs; |
| 330 } |
| 331 |
| 332 // Helper class for decoding packed ARM relocation data. |
| 333 // http://en.wikipedia.org/wiki/LEB128 |
| 334 class Leb128Decoder { |
| 335 public: |
| 336 explicit Leb128Decoder(const uint8_t* encoding) |
| 337 : encoding_(encoding), cursor_(0) { } |
| 338 |
| 339 uint32_t Dequeue() { |
| 340 size_t extent = cursor_; |
| 341 while (encoding_[extent] >> 7) |
| 342 extent++; |
| 343 |
| 344 uint32_t value = 0; |
| 345 for (size_t i = extent; i > cursor_; --i) { |
| 346 value = (value << 7) | (encoding_[i] & 127); |
| 347 } |
| 348 value = (value << 7) | (encoding_[cursor_] & 127); |
| 349 |
| 350 cursor_ = extent + 1; |
| 351 return value; |
| 352 } |
| 353 |
| 354 private: |
| 355 const uint8_t* encoding_; |
| 356 size_t cursor_; |
| 357 }; |
| 358 |
| 359 bool ElfRelocations::ApplyArmPackedRelocs(Error* error) { |
| 360 if (!arm_packed_relocs_) |
| 361 return true; |
| 362 |
| 363 Leb128Decoder decoder(arm_packed_relocs_); |
| 364 |
| 365 // Check for the initial APR1 header. |
| 366 if (decoder.Dequeue() != 'A' || decoder.Dequeue() != 'P' || |
| 367 decoder.Dequeue() != 'R' || decoder.Dequeue() != '1') { |
| 368 error->Format("Bad packed relocations ident, expected APR1"); |
| 369 return false; |
| 370 } |
| 371 |
| 372 // Find the count of pairs and the start address. |
| 373 size_t pairs = decoder.Dequeue(); |
| 374 const Elf32_Addr start_address = decoder.Dequeue(); |
| 375 |
| 376 // Emit initial R_ARM_RELATIVE relocation. |
| 377 Elf32_Rel relocation = {start_address, R_ARM_RELATIVE}; |
| 378 const ELF::Addr sym_addr = 0; |
| 379 const bool resolved = false; |
| 380 if (!ApplyRelReloc(&relocation, sym_addr, resolved, error)) |
| 381 return false; |
| 382 |
| 383 size_t unpacked_count = 1; |
| 384 |
| 385 // Emit relocations for each count-delta pair. |
| 386 while (pairs) { |
| 387 size_t count = decoder.Dequeue(); |
| 388 const size_t delta = decoder.Dequeue(); |
| 389 |
| 390 // Emit count R_ARM_RELATIVE relocations with delta offset. |
| 391 while (count) { |
| 392 relocation.r_offset += delta; |
| 393 if (!ApplyRelReloc(&relocation, sym_addr, resolved, error)) |
| 394 return false; |
| 395 unpacked_count++; |
| 396 count--; |
| 397 } |
| 398 pairs--; |
| 399 } |
| 400 |
| 401 RLOG("%s: unpacked_count=%d\n", __FUNCTION__, unpacked_count); |
| 402 return true; |
| 403 } |
| 404 #endif // __arm__ |
| 405 |
| 320 bool ElfRelocations::ApplyRelaReloc(const ELF::Rela* rela, | 406 bool ElfRelocations::ApplyRelaReloc(const ELF::Rela* rela, |
| 321 ELF::Addr sym_addr, | 407 ELF::Addr sym_addr, |
| 322 bool resolved CRAZY_UNUSED, | 408 bool resolved CRAZY_UNUSED, |
| 323 Error* error) { | 409 Error* error) { |
| 324 const ELF::Word rela_type = ELF_R_TYPE(rela->r_info); | 410 const ELF::Word rela_type = ELF_R_TYPE(rela->r_info); |
| 325 const ELF::Word CRAZY_UNUSED rela_symbol = ELF_R_SYM(rela->r_info); | 411 const ELF::Word CRAZY_UNUSED rela_symbol = ELF_R_SYM(rela->r_info); |
| 326 const ELF::Sword CRAZY_UNUSED addend = rela->r_addend; | 412 const ELF::Sword CRAZY_UNUSED addend = rela->r_addend; |
| 327 | 413 |
| 328 const ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); | 414 const ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); |
| 329 | 415 |
| (...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 if (got_addr < src_addr || got_addr >= src_addr + size) | 906 if (got_addr < src_addr || got_addr >= src_addr + size) |
| 821 continue; | 907 continue; |
| 822 ELF::Addr* dst_ptr = reinterpret_cast<ELF::Addr*>(got_addr + dst_delta); | 908 ELF::Addr* dst_ptr = reinterpret_cast<ELF::Addr*>(got_addr + dst_delta); |
| 823 *dst_ptr += map_delta; | 909 *dst_ptr += map_delta; |
| 824 } | 910 } |
| 825 } | 911 } |
| 826 #endif | 912 #endif |
| 827 } | 913 } |
| 828 | 914 |
| 829 } // namespace crazy | 915 } // namespace crazy |
| OLD | NEW |