| 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;
|
| + }
|
| +
|
| + 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;
|
| + }
|
| + fd.Close();
|
| +
|
| + uint8_t* packed_data = buffer.Release();
|
| + return packed_data;
|
| +}
|
| +
|
| +#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_;
|
| +#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;
|
|
|