Chromium Code Reviews| Index: third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp |
| diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp |
| index 591a1fdadd1eb76f8e85beaa10b6b47e5f212117..3be989889b039172288b6d5f5194776a2f2d646c 100644 |
| --- a/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp |
| +++ b/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp |
| @@ -10,6 +10,7 @@ |
| #include "crazy_linker_elf_symbols.h" |
| #include "crazy_linker_elf_view.h" |
| #include "crazy_linker_error.h" |
| +#include "crazy_linker_system.h" |
| #include "crazy_linker_util.h" |
| #include "linker_phdr.h" |
| @@ -65,6 +66,14 @@ |
| #endif // __i386__ |
| +// Processor-specific extension dynamic tags for packed relocations. |
| +#ifdef __arm__ |
| + |
| +#define DT_ANDROID_ARM_REL_OFFSET (DT_LOPROC) |
| +#define DT_ANDROID_ARM_REL_SIZE (DT_LOPROC + 1) |
|
rmcilroy
2014/06/18 10:56:05
nit - just move this up to the preceding ifdef __a
simonb1
2014/06/18 15:41:28
Moved to crazy_linker_shared_library.cpp in patch
|
| + |
| +#endif // __arm__ |
| + |
| namespace crazy { |
| namespace { |
| @@ -221,6 +230,16 @@ bool ElfRelocations::Init(const ElfView* view, Error* error) { |
| has_text_relocations_ ? "true" : "false", |
| has_symbolic_ ? "true" : "false"); |
| break; |
| +#if defined(__arm__) |
| + case DT_ANDROID_ARM_REL_OFFSET: |
| + arm_packed_relocations_ = dyn.GetOffset(); |
| + RLOG(" DT_ANDROID_ARM_REL_OFFSET addr=%p\n", arm_packed_relocations_); |
| + break; |
| + case DT_ANDROID_ARM_REL_SIZE: |
| + arm_packed_relocations_size_ = dyn.GetValue(); |
| + RLOG(" DT_ANDROID_ARM_REL_SIZE=%d\n", arm_packed_relocations_size_); |
| + break; |
| +#endif |
| #if defined(__mips__) |
| case DT_MIPS_SYMTABNO: |
| RLOG(" DT_MIPS_SYMTABNO value=%d\n", dyn_value); |
| @@ -261,6 +280,7 @@ bool ElfRelocations::Init(const ElfView* view, Error* error) { |
| bool ElfRelocations::ApplyAll(const ElfSymbols* symbols, |
| SymbolResolver* resolver, |
| + const char* full_path CRAZY_UNUSED, |
|
rmcilroy
2014/06/18 10:56:05
Rather than passing the full path here, and having
simonb1
2014/06/18 15:41:28
Done. It's a bit more diffuse, so greater occurre
|
| Error* error) { |
| LOG("%s: Enter\n", __FUNCTION__); |
| @@ -286,7 +306,7 @@ bool ElfRelocations::ApplyAll(const ElfSymbols* symbols, |
| return false; |
| } |
| - else if (relocations_type_ == DT_RELA) { |
| + if (relocations_type_ == DT_RELA) { |
| if (!ApplyRelaRelocs(reinterpret_cast<ELF::Rela*>(plt_relocations_), |
| plt_relocations_size_ / sizeof(ELF::Rela), |
| symbols, |
| @@ -301,6 +321,11 @@ bool ElfRelocations::ApplyAll(const ElfSymbols* symbols, |
| return false; |
| } |
| +#ifdef __arm__ |
| + if (!ApplyArmPackedRelocs(full_path, error)) |
| + return false; |
| +#endif |
| + |
| #ifdef __mips__ |
| if (!RelocateMipsGot(symbols, resolver, error)) |
| return false; |
| @@ -641,6 +666,126 @@ bool ElfRelocations::ApplyRelaRelocs(const ELF::Rela* rela, |
| return true; |
| } |
| +#ifdef __arm__ |
| + |
| +// Helper class for decoding packed ARM relocation data. |
| +// http://en.wikipedia.org/wiki/LEB128 |
| +class Leb128Decoder { |
| + public: |
| + explicit Leb128Decoder(const uint8_t* encoding) |
| + : encoding_(encoding), cursor_(0) { } |
| + |
| + uint32_t Dequeue() { |
| + size_t extent = cursor_; |
| + while (encoding_[extent] >> 7) |
| + extent++; |
| + |
| + uint32_t value = 0; |
| + for (size_t i = extent; i > cursor_; --i) { |
| + value = (value << 7) | (encoding_[i] & 127); |
| + } |
| + value = (value << 7) | (encoding_[cursor_] & 127); |
| + |
| + cursor_ = extent + 1; |
| + return value; |
| + } |
| + |
| + private: |
| + const uint8_t* encoding_; |
| + size_t cursor_; |
| +}; |
| + |
| +// Helper class to provide a simple scoped buffer. ScopedPtr is not |
| +// usable here because it calls delete, not delete []. |
| +class ScopedBuffer { |
| + public: |
| + explicit ScopedBuffer(size_t bytes) : buffer_(new uint8_t[bytes]) { } |
| + ~ScopedBuffer() { delete [] buffer_; } |
| + |
| + uint8_t* Get() { return buffer_; } |
| + |
| + private: |
| + uint8_t* buffer_; |
| +}; |
| + |
| +bool ElfRelocations::ApplyArmPackedRelocs(const char* full_path, |
| + Error* error) { |
| + RLOG("%s: packed_relocations=%p, packed_relocations_size=%d\n", |
| + __FUNCTION__, |
| + arm_packed_relocations_, |
| + arm_packed_relocations_size_); |
| + |
| + if (arm_packed_relocations_size_ == 0) |
| + return true; |
| + |
| + // Allocate and then read the packed relocations section. |
| + ScopedBuffer scoped_packed_data(arm_packed_relocations_size_); |
| + uint8_t* packed_data = scoped_packed_data.Get(); |
| + |
| + FileDescriptor fd; |
| + if (!fd.OpenReadOnly(full_path)) { |
| + error->Format("Error opening file '%s'", full_path); |
| + return false; |
| + } |
| + if (fd.SeekTo(arm_packed_relocations_) == -1) { |
| + error->Format("Error seeking to %d in file '%s'", |
| + arm_packed_relocations_, |
| + full_path); |
| + return false; |
| + } |
| + const ssize_t bytes = fd.Read(packed_data, arm_packed_relocations_size_); |
| + if (bytes != arm_packed_relocations_size_) { |
| + error->Format("Error reading %d bytes from file '%s'", |
| + arm_packed_relocations_size_, |
| + full_path); |
| + return false; |
| + } |
| + fd.Close(); |
| + |
| + Leb128Decoder decoder(packed_data); |
| + |
| + // Check for the initial APR1 header. |
| + if (decoder.Dequeue() != 'A' || decoder.Dequeue() != 'P' || |
| + decoder.Dequeue() != 'R' || decoder.Dequeue() != '1') { |
| + error->Format("Bad packed relocations ident, expected APR1"); |
| + return false; |
| + } |
| + |
| + // Find the count of pairs and the start address. |
| + size_t pairs = decoder.Dequeue(); |
| + const Elf32_Addr start_address = decoder.Dequeue(); |
| + |
| + // Emit initial R_ARM_RELATIVE relocation. |
| + Elf32_Rel relocation = {start_address, R_ARM_RELATIVE}; |
| + const ELF::Addr sym_addr = 0; |
| + const bool resolved = false; |
| + if (!ApplyRelReloc(&relocation, sym_addr, resolved, error)) |
| + return false; |
| + |
| + size_t unpacked_count = 1; |
| + |
| + // Emit relocations for each count-delta pair. |
| + while (pairs) { |
| + size_t count = decoder.Dequeue(); |
| + const size_t delta = decoder.Dequeue(); |
| + |
| + // Emit count R_ARM_RELATIVE relocations with delta offset. |
| + while (count) { |
| + relocation.r_offset += delta; |
| + if (!ApplyRelReloc(&relocation, sym_addr, resolved, error)) |
| + return false; |
| + unpacked_count++; |
| + count--; |
| + } |
| + pairs--; |
| + } |
| + |
| + RLOG("%s: unpacked_count=%d\n", __FUNCTION__, unpacked_count); |
| + return true; |
| +} |
| + |
| +#endif // __arm__ |
| + |
| #ifdef __mips__ |
| bool ElfRelocations::RelocateMipsGot(const ElfSymbols* symbols, |
| SymbolResolver* resolver, |