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 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 error)) | 304 error)) |
304 return false; | 305 return false; |
305 if (!ApplyRelaRelocs(reinterpret_cast<ELF::Rela*>(relocations_), | 306 if (!ApplyRelaRelocs(reinterpret_cast<ELF::Rela*>(relocations_), |
306 relocations_size_ / sizeof(ELF::Rela), | 307 relocations_size_ / sizeof(ELF::Rela), |
307 symbols, | 308 symbols, |
308 resolver, | 309 resolver, |
309 error)) | 310 error)) |
310 return false; | 311 return false; |
311 } | 312 } |
312 | 313 |
| 314 #ifdef __arm__ |
| 315 if (!ApplyArmPackedRelocs(error)) |
| 316 return false; |
| 317 #endif |
| 318 |
313 #ifdef __mips__ | 319 #ifdef __mips__ |
314 if (!RelocateMipsGot(symbols, resolver, error)) | 320 if (!RelocateMipsGot(symbols, resolver, error)) |
315 return false; | 321 return false; |
316 #endif | 322 #endif |
317 | 323 |
318 if (has_text_relocations_) { | 324 if (has_text_relocations_) { |
319 if (phdr_table_protect_segments(phdr_, phdr_count_, load_bias_) < 0) { | 325 if (phdr_table_protect_segments(phdr_, phdr_count_, load_bias_) < 0) { |
320 error->Format("Can't reprotect loadable segments: %s", strerror(errno)); | 326 error->Format("Can't reprotect loadable segments: %s", strerror(errno)); |
321 return false; | 327 return false; |
322 } | 328 } |
323 } | 329 } |
324 | 330 |
325 LOG("%s: Done\n", __FUNCTION__); | 331 LOG("%s: Done\n", __FUNCTION__); |
326 return true; | 332 return true; |
327 } | 333 } |
328 | 334 |
| 335 #ifdef __arm__ |
| 336 |
| 337 void ElfRelocations::RegisterArmPackedRelocs(uint8_t* arm_packed_relocs) { |
| 338 arm_packed_relocs_ = arm_packed_relocs; |
| 339 } |
| 340 |
| 341 // Helper class for decoding packed ARM relocation data. |
| 342 // http://en.wikipedia.org/wiki/LEB128 |
| 343 class Leb128Decoder { |
| 344 public: |
| 345 explicit Leb128Decoder(const uint8_t* encoding) |
| 346 : encoding_(encoding), cursor_(0) { } |
| 347 |
| 348 uint32_t Dequeue() { |
| 349 size_t extent = cursor_; |
| 350 while (encoding_[extent] >> 7) |
| 351 extent++; |
| 352 |
| 353 uint32_t value = 0; |
| 354 for (size_t i = extent; i > cursor_; --i) { |
| 355 value = (value << 7) | (encoding_[i] & 127); |
| 356 } |
| 357 value = (value << 7) | (encoding_[cursor_] & 127); |
| 358 |
| 359 cursor_ = extent + 1; |
| 360 return value; |
| 361 } |
| 362 |
| 363 private: |
| 364 const uint8_t* encoding_; |
| 365 size_t cursor_; |
| 366 }; |
| 367 |
| 368 bool ElfRelocations::ApplyArmPackedRelocs(Error* error) { |
| 369 if (!arm_packed_relocs_) |
| 370 return true; |
| 371 |
| 372 Leb128Decoder decoder(arm_packed_relocs_); |
| 373 |
| 374 // Check for the initial APR1 header. |
| 375 if (decoder.Dequeue() != 'A' || decoder.Dequeue() != 'P' || |
| 376 decoder.Dequeue() != 'R' || decoder.Dequeue() != '1') { |
| 377 error->Format("Bad packed relocations ident, expected APR1"); |
| 378 return false; |
| 379 } |
| 380 |
| 381 // Find the count of pairs and the start address. |
| 382 size_t pairs = decoder.Dequeue(); |
| 383 const Elf32_Addr start_address = decoder.Dequeue(); |
| 384 |
| 385 // Emit initial R_ARM_RELATIVE relocation. |
| 386 Elf32_Rel relocation = {start_address, R_ARM_RELATIVE}; |
| 387 const ELF::Addr sym_addr = 0; |
| 388 const bool resolved = false; |
| 389 if (!ApplyRelReloc(&relocation, sym_addr, resolved, error)) |
| 390 return false; |
| 391 |
| 392 size_t unpacked_count = 1; |
| 393 |
| 394 // Emit relocations for each count-delta pair. |
| 395 while (pairs) { |
| 396 size_t count = decoder.Dequeue(); |
| 397 const size_t delta = decoder.Dequeue(); |
| 398 |
| 399 // Emit count R_ARM_RELATIVE relocations with delta offset. |
| 400 while (count) { |
| 401 relocation.r_offset += delta; |
| 402 if (!ApplyRelReloc(&relocation, sym_addr, resolved, error)) |
| 403 return false; |
| 404 unpacked_count++; |
| 405 count--; |
| 406 } |
| 407 pairs--; |
| 408 } |
| 409 |
| 410 RLOG("%s: unpacked_count=%d\n", __FUNCTION__, unpacked_count); |
| 411 return true; |
| 412 } |
| 413 #endif // __arm__ |
| 414 |
329 bool ElfRelocations::ApplyRelaReloc(const ELF::Rela* rela, | 415 bool ElfRelocations::ApplyRelaReloc(const ELF::Rela* rela, |
330 ELF::Addr sym_addr, | 416 ELF::Addr sym_addr, |
331 bool resolved CRAZY_UNUSED, | 417 bool resolved CRAZY_UNUSED, |
332 Error* error) { | 418 Error* error) { |
333 const ELF::Word rela_type = ELF_R_TYPE(rela->r_info); | 419 const ELF::Word rela_type = ELF_R_TYPE(rela->r_info); |
334 const ELF::Word CRAZY_UNUSED rela_symbol = ELF_R_SYM(rela->r_info); | 420 const ELF::Word CRAZY_UNUSED rela_symbol = ELF_R_SYM(rela->r_info); |
335 const ELF::Sword CRAZY_UNUSED addend = rela->r_addend; | 421 const ELF::Sword CRAZY_UNUSED addend = rela->r_addend; |
336 | 422 |
337 const ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); | 423 const ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); |
338 | 424 |
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
835 if (got_addr < src_addr || got_addr >= src_addr + size) | 921 if (got_addr < src_addr || got_addr >= src_addr + size) |
836 continue; | 922 continue; |
837 ELF::Addr* dst_ptr = reinterpret_cast<ELF::Addr*>(got_addr + dst_delta); | 923 ELF::Addr* dst_ptr = reinterpret_cast<ELF::Addr*>(got_addr + dst_delta); |
838 *dst_ptr += map_delta; | 924 *dst_ptr += map_delta; |
839 } | 925 } |
840 } | 926 } |
841 #endif | 927 #endif |
842 } | 928 } |
843 | 929 |
844 } // namespace crazy | 930 } // namespace crazy |
OLD | NEW |