Chromium Code Reviews| Index: third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp |
| diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp |
| index e01649992cd40104afaaf7b436c6c25071f3a173..0c324344f8628276f4fd601b709e4ef660f71a94 100644 |
| --- a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp |
| +++ b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp |
| @@ -58,6 +58,14 @@ |
| #define DT_PREINIT_ARRAYSZ 33 |
| #endif |
| +// 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) |
| + |
| +#endif // __arm__ |
| + |
| namespace crazy { |
| namespace { |
| @@ -148,6 +156,57 @@ class SharedLibraryResolver : public ElfRelocations::SymbolResolver { |
| Vector<LibraryView*>* dependencies_; |
| }; |
| +#ifdef __arm__ |
| + |
| +// 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_; } |
| + |
| + uint8_t* Release() { |
| + uint8_t* ptr = buffer_; |
| + buffer_ = NULL; |
| + return ptr; |
| + } |
| + |
| + private: |
| + uint8_t* buffer_; |
| +}; |
| + |
| +// Read an .android.rel.dyn ARM packed relocations section. |
| +// Returns an allocated buffer holding the data, or NULL on error. |
| +uint8_t* ReadArmPackedRelocs(const char* full_path, |
| + off_t offset, |
| + size_t bytes, |
| + Error* error) { |
| + FileDescriptor fd; |
| + if (!fd.OpenReadOnly(full_path)) { |
| + error->Format("Error opening file '%s'", full_path); |
| + return NULL; |
| + } |
| + if (fd.SeekTo(offset) == -1) { |
| + error->Format("Error seeking to %d in file '%s'", offset, full_path); |
| + return NULL; |
|
rmcilroy
2014/06/24 09:47:22
close(fd)
simonb (inactive)
2014/06/24 11:43:55
Not needed. FileDescriptor is scoped (calls Close
|
| + } |
| + |
| + ScopedBuffer buffer(bytes); |
| + const ssize_t bytes_read = fd.Read(buffer.Get(), bytes); |
| + if (bytes_read != bytes) { |
| + error->Format("Error reading %d bytes from file '%s'", bytes, full_path); |
| + return NULL; |
|
rmcilroy
2014/06/24 09:47:22
ditto
simonb (inactive)
2014/06/24 11:43:55
Ditto.
|
| + } |
| + fd.Close(); |
| + |
| + uint8_t* packed_data = buffer.Release(); |
| + return packed_data; |
|
rmcilroy
2014/06/24 09:47:22
nit - just "return buffer.Release();"
simonb (inactive)
2014/06/24 11:43:55
I find this more readable as it clearly documents
|
| +} |
| + |
| +#endif // __arm__ |
| + |
| } // namespace |
| SharedLibrary::SharedLibrary() { ::memset(this, 0, sizeof(*this)); } |
| @@ -156,6 +215,10 @@ SharedLibrary::~SharedLibrary() { |
| // Ensure the library is unmapped on destruction. |
| if (view_.load_address()) |
| munmap(reinterpret_cast<void*>(view_.load_address()), view_.load_size()); |
| + |
| +#ifdef __arm__ |
| + delete [] arm_packed_relocs_; |
|
rmcilroy
2014/06/24 09:47:22
nit - you could make arm_packed_relocs_ a ScopedBu
simonb (inactive)
2014/06/24 11:43:55
Not really. ScopedBuffer is designed to be stack-
|
| +#endif |
| } |
| bool SharedLibrary::Load(const char* full_path, |
| @@ -209,6 +272,9 @@ bool SharedLibrary::Load(const char* full_path, |
| LOG("%s: Extracting ARM.exidx table for %s\n", __FUNCTION__, base_name_); |
| (void)phdr_table_get_arm_exidx( |
| phdr(), phdr_count(), load_bias(), &arm_exidx_, &arm_exidx_count_); |
| + |
| + off_t arm_packed_relocs_offset = 0; |
| + size_t arm_packed_relocs_size = 0; |
| #endif |
| LOG("%s: Parsing dynamic table for %s\n", __FUNCTION__, base_name_); |
| @@ -269,6 +335,16 @@ bool SharedLibrary::Load(const char* full_path, |
| if (dyn_value & DF_SYMBOLIC) |
| has_DT_SYMBOLIC_ = true; |
| break; |
| +#if defined(__arm__) |
| + case DT_ANDROID_ARM_REL_OFFSET: |
| + arm_packed_relocs_offset = dyn.GetOffset(); |
| + LOG(" DT_ANDROID_ARM_REL_OFFSET addr=%p\n", arm_packed_relocs_offset); |
| + break; |
| + case DT_ANDROID_ARM_REL_SIZE: |
| + arm_packed_relocs_size = dyn.GetValue(); |
| + LOG(" DT_ANDROID_ARM_REL_SIZE=%d\n", arm_packed_relocs_size); |
| + break; |
| +#endif |
| #if defined(__mips__) |
| case DT_MIPS_RLD_MAP: |
| *dyn.GetValuePointer() = |
| @@ -280,6 +356,29 @@ bool SharedLibrary::Load(const char* full_path, |
| } |
| } |
| +#ifdef __arm__ |
| + // If ARM packed relocations are present in the target library, read the |
| + // section data and save it in arm_packed_relocs_. |
| + if (arm_packed_relocs_offset && arm_packed_relocs_size) { |
| + LOG("%s: ARM packed relocations found at offset %d, %d bytes\n", |
| + __FUNCTION__, |
| + arm_packed_relocs_offset, |
| + arm_packed_relocs_size); |
| + |
| + arm_packed_relocs_ = |
| + ReadArmPackedRelocs(full_path, |
| + arm_packed_relocs_offset + file_offset, |
| + arm_packed_relocs_size, |
| + error); |
| + if (!arm_packed_relocs_) |
| + return false; |
| + |
| + LOG("%s: ARM packed relocations stored at %p\n", |
| + __FUNCTION__, |
| + arm_packed_relocs_); |
| + } |
| +#endif |
| + |
| LOG("%s: Load complete for %s\n", __FUNCTION__, base_name_); |
| return true; |
| } |
| @@ -295,6 +394,10 @@ bool SharedLibrary::Relocate(LibraryList* lib_list, |
| if (!relocations.Init(&view_, error)) |
| return false; |
| +#ifdef __arm__ |
| + relocations.RegisterArmPackedRelocs(arm_packed_relocs_); |
| +#endif |
| + |
| SharedLibraryResolver resolver(this, lib_list, dependencies); |
| if (!relocations.ApplyAll(&symbols_, &resolver, error)) |
| return false; |