am 52a0f014: Merge "Fix long lines and replace macros with functions."
				
					
				
			* commit '52a0f01421fde3cd4f879b491a9f491d792fa2d5': Fix long lines and replace macros with functions.
This commit is contained in:
		@@ -221,7 +221,7 @@ static void send_debuggerd_packet(siginfo_t* info) {
 | 
				
			|||||||
  if (ret != 0) {
 | 
					  if (ret != 0) {
 | 
				
			||||||
    if (ret == EBUSY) {
 | 
					    if (ret == EBUSY) {
 | 
				
			||||||
      __libc_format_log(ANDROID_LOG_INFO, "libc",
 | 
					      __libc_format_log(ANDROID_LOG_INFO, "libc",
 | 
				
			||||||
                        "Another thread has contacted debuggerd first, stop and wait for process to die.");
 | 
					          "Another thread contacted debuggerd first; not contacting debuggerd.");
 | 
				
			||||||
      // This will never complete since the lock is never released.
 | 
					      // This will never complete since the lock is never released.
 | 
				
			||||||
      pthread_mutex_lock(&crash_mutex);
 | 
					      pthread_mutex_lock(&crash_mutex);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -140,10 +140,13 @@ size_t linker_get_error_buffer_size() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// This function is an empty stub where GDB locates a breakpoint to get notified
 | 
					// This function is an empty stub where GDB locates a breakpoint to get notified
 | 
				
			||||||
// about linker activity.
 | 
					// about linker activity.
 | 
				
			||||||
extern "C" void __attribute__((noinline)) __attribute__((visibility("default"))) rtld_db_dlactivity();
 | 
					extern "C"
 | 
				
			||||||
 | 
					void __attribute__((noinline)) __attribute__((visibility("default"))) rtld_db_dlactivity();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static pthread_mutex_t g__r_debug_mutex = PTHREAD_MUTEX_INITIALIZER;
 | 
					static pthread_mutex_t g__r_debug_mutex = PTHREAD_MUTEX_INITIALIZER;
 | 
				
			||||||
static r_debug _r_debug = {1, nullptr, reinterpret_cast<uintptr_t>(&rtld_db_dlactivity), r_debug::RT_CONSISTENT, 0};
 | 
					static r_debug _r_debug =
 | 
				
			||||||
 | 
					    {1, nullptr, reinterpret_cast<uintptr_t>(&rtld_db_dlactivity), r_debug::RT_CONSISTENT, 0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static link_map* r_debug_tail = 0;
 | 
					static link_map* r_debug_tail = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void insert_soinfo_into_debug_map(soinfo* info) {
 | 
					static void insert_soinfo_into_debug_map(soinfo* info) {
 | 
				
			||||||
@@ -233,7 +236,8 @@ void SoinfoListAllocator::free(LinkedListEntry<soinfo>* entry) {
 | 
				
			|||||||
  g_soinfo_links_allocator.free(entry);
 | 
					  g_soinfo_links_allocator.free(entry);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static soinfo* soinfo_alloc(const char* name, struct stat* file_stat, off64_t file_offset, uint32_t rtld_flags) {
 | 
					static soinfo* soinfo_alloc(const char* name, struct stat* file_stat,
 | 
				
			||||||
 | 
					                            off64_t file_offset, uint32_t rtld_flags) {
 | 
				
			||||||
  if (strlen(name) >= SOINFO_NAME_LEN) {
 | 
					  if (strlen(name) >= SOINFO_NAME_LEN) {
 | 
				
			||||||
    DL_ERR("library name \"%s\" too long", name);
 | 
					    DL_ERR("library name \"%s\" too long", name);
 | 
				
			||||||
    return nullptr;
 | 
					    return nullptr;
 | 
				
			||||||
@@ -434,7 +438,8 @@ ElfW(Sym)* soinfo::elf_lookup(SymbolName& symbol_name) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  for (uint32_t n = bucket_[hash % nbucket_]; n != 0; n = chain_[n]) {
 | 
					  for (uint32_t n = bucket_[hash % nbucket_]; n != 0; n = chain_[n]) {
 | 
				
			||||||
    ElfW(Sym)* s = symtab_ + n;
 | 
					    ElfW(Sym)* s = symtab_ + n;
 | 
				
			||||||
    if (strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 && is_symbol_global_and_defined(this, s)) {
 | 
					    if (strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 &&
 | 
				
			||||||
 | 
					        is_symbol_global_and_defined(this, s)) {
 | 
				
			||||||
      TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
 | 
					      TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
 | 
				
			||||||
               symbol_name.get_name(), name, reinterpret_cast<void*>(s->st_value),
 | 
					               symbol_name.get_name(), name, reinterpret_cast<void*>(s->st_value),
 | 
				
			||||||
               static_cast<size_t>(s->st_size));
 | 
					               static_cast<size_t>(s->st_size));
 | 
				
			||||||
@@ -448,7 +453,8 @@ ElfW(Sym)* soinfo::elf_lookup(SymbolName& symbol_name) {
 | 
				
			|||||||
  return nullptr;
 | 
					  return nullptr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
soinfo::soinfo(const char* name, const struct stat* file_stat, off64_t file_offset, int rtld_flags) {
 | 
					soinfo::soinfo(const char* name, const struct stat* file_stat,
 | 
				
			||||||
 | 
					               off64_t file_offset, int rtld_flags) {
 | 
				
			||||||
  memset(this, 0, sizeof(*this));
 | 
					  memset(this, 0, sizeof(*this));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  strlcpy(this->name, name, sizeof(this->name));
 | 
					  strlcpy(this->name, name, sizeof(this->name));
 | 
				
			||||||
@@ -1002,7 +1008,8 @@ static soinfo* load_library(LoadTaskList& load_tasks,
 | 
				
			|||||||
    return nullptr;
 | 
					    return nullptr;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (file_offset >= file_stat.st_size) {
 | 
					  if (file_offset >= file_stat.st_size) {
 | 
				
			||||||
    DL_ERR("file offset for the library \"%s\" >= file size: %" PRId64 " >= %" PRId64, name, file_offset, file_stat.st_size);
 | 
					    DL_ERR("file offset for the library \"%s\" >= file size: %" PRId64 " >= %" PRId64,
 | 
				
			||||||
 | 
					        name, file_offset, file_stat.st_size);
 | 
				
			||||||
    return nullptr;
 | 
					    return nullptr;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1014,7 +1021,8 @@ static soinfo* load_library(LoadTaskList& load_tasks,
 | 
				
			|||||||
        si->get_st_dev() == file_stat.st_dev &&
 | 
					        si->get_st_dev() == file_stat.st_dev &&
 | 
				
			||||||
        si->get_st_ino() == file_stat.st_ino &&
 | 
					        si->get_st_ino() == file_stat.st_ino &&
 | 
				
			||||||
        si->get_file_offset() == file_offset) {
 | 
					        si->get_file_offset() == file_offset) {
 | 
				
			||||||
      TRACE("library \"%s\" is already loaded under different name/path \"%s\" - will return existing soinfo", name, si->name);
 | 
					      TRACE("library \"%s\" is already loaded under different name/path \"%s\" - "
 | 
				
			||||||
 | 
					          "will return existing soinfo", name, si->name);
 | 
				
			||||||
      return si;
 | 
					      return si;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1067,7 +1075,8 @@ static soinfo *find_loaded_library_by_soname(const char* name) {
 | 
				
			|||||||
  return nullptr;
 | 
					  return nullptr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static soinfo* find_library_internal(LoadTaskList& load_tasks, const char* name, int rtld_flags, const android_dlextinfo* extinfo) {
 | 
					static soinfo* find_library_internal(LoadTaskList& load_tasks, const char* name,
 | 
				
			||||||
 | 
					                                     int rtld_flags, const android_dlextinfo* extinfo) {
 | 
				
			||||||
  soinfo* si = find_loaded_library_by_soname(name);
 | 
					  soinfo* si = find_loaded_library_by_soname(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Library might still be loaded, the accurate detection
 | 
					  // Library might still be loaded, the accurate detection
 | 
				
			||||||
@@ -1141,7 +1150,8 @@ static bool find_libraries(soinfo* start_with, const char* const library_names[]
 | 
				
			|||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Step 1: load and pre-link all DT_NEEDED libraries in breadth first order.
 | 
					  // Step 1: load and pre-link all DT_NEEDED libraries in breadth first order.
 | 
				
			||||||
  for (LoadTask::unique_ptr task(load_tasks.pop_front()); task.get() != nullptr; task.reset(load_tasks.pop_front())) {
 | 
					  for (LoadTask::unique_ptr task(load_tasks.pop_front());
 | 
				
			||||||
 | 
					      task.get() != nullptr; task.reset(load_tasks.pop_front())) {
 | 
				
			||||||
    soinfo* si = find_library_internal(load_tasks, task->get_name(), rtld_flags, extinfo);
 | 
					    soinfo* si = find_library_internal(load_tasks, task->get_name(), rtld_flags, extinfo);
 | 
				
			||||||
    if (si == nullptr) {
 | 
					    if (si == nullptr) {
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
@@ -1320,8 +1330,8 @@ void do_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
 | 
				
			|||||||
  // snprintf again.
 | 
					  // snprintf again.
 | 
				
			||||||
  size_t required_len = strlen(kDefaultLdPaths[0]) + strlen(kDefaultLdPaths[1]) + 2;
 | 
					  size_t required_len = strlen(kDefaultLdPaths[0]) + strlen(kDefaultLdPaths[1]) + 2;
 | 
				
			||||||
  if (buffer_size < required_len) {
 | 
					  if (buffer_size < required_len) {
 | 
				
			||||||
    __libc_fatal("android_get_LD_LIBRARY_PATH failed, buffer too small: buffer len %zu, required len %zu",
 | 
					    __libc_fatal("android_get_LD_LIBRARY_PATH failed, buffer too small: "
 | 
				
			||||||
                 buffer_size, required_len);
 | 
					                 "buffer len %zu, required len %zu", buffer_size, required_len);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  char* end = stpcpy(buffer, kDefaultLdPaths[0]);
 | 
					  char* end = stpcpy(buffer, kDefaultLdPaths[0]);
 | 
				
			||||||
  *end = ':';
 | 
					  *end = ':';
 | 
				
			||||||
@@ -1344,7 +1354,8 @@ soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) == 0 &&
 | 
					    if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) == 0 &&
 | 
				
			||||||
        (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
 | 
					        (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
 | 
				
			||||||
      DL_ERR("invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without ANDROID_DLEXT_USE_LIBRARY_FD): 0x%" PRIx64, extinfo->flags);
 | 
					      DL_ERR("invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without "
 | 
				
			||||||
 | 
					          "ANDROID_DLEXT_USE_LIBRARY_FD): 0x%" PRIx64, extinfo->flags);
 | 
				
			||||||
      return nullptr;
 | 
					      return nullptr;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1366,7 +1377,8 @@ static ElfW(Addr) call_ifunc_resolver(ElfW(Addr) resolver_addr) {
 | 
				
			|||||||
  typedef ElfW(Addr) (*ifunc_resolver_t)(void);
 | 
					  typedef ElfW(Addr) (*ifunc_resolver_t)(void);
 | 
				
			||||||
  ifunc_resolver_t ifunc_resolver = reinterpret_cast<ifunc_resolver_t>(resolver_addr);
 | 
					  ifunc_resolver_t ifunc_resolver = reinterpret_cast<ifunc_resolver_t>(resolver_addr);
 | 
				
			||||||
  ElfW(Addr) ifunc_addr = ifunc_resolver();
 | 
					  ElfW(Addr) ifunc_addr = ifunc_resolver();
 | 
				
			||||||
  TRACE_TYPE(RELO, "Called ifunc_resolver@%p. The result is %p", ifunc_resolver, reinterpret_cast<void*>(ifunc_addr));
 | 
					  TRACE_TYPE(RELO, "Called ifunc_resolver@%p. The result is %p",
 | 
				
			||||||
 | 
					      ifunc_resolver, reinterpret_cast<void*>(ifunc_addr));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return ifunc_addr;
 | 
					  return ifunc_addr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1378,7 +1390,8 @@ static ElfW(Addr) get_addend(ElfW(Rela)* rela, ElfW(Addr) reloc_addr __unused) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
static ElfW(Addr) get_addend(ElfW(Rel)* rel, ElfW(Addr) reloc_addr) {
 | 
					static ElfW(Addr) get_addend(ElfW(Rel)* rel, ElfW(Addr) reloc_addr) {
 | 
				
			||||||
  if (ELFW(R_TYPE)(rel->r_info) == R_GENERIC_RELATIVE || ELFW(R_TYPE)(rel->r_info) == R_GENERIC_IRELATIVE) {
 | 
					  if (ELFW(R_TYPE)(rel->r_info) == R_GENERIC_RELATIVE ||
 | 
				
			||||||
 | 
					      ELFW(R_TYPE)(rel->r_info) == R_GENERIC_IRELATIVE) {
 | 
				
			||||||
    return *reinterpret_cast<ElfW(Addr)*>(reloc_addr);
 | 
					    return *reinterpret_cast<ElfW(Addr)*>(reloc_addr);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return 0;
 | 
					  return 0;
 | 
				
			||||||
@@ -1386,7 +1399,8 @@ static ElfW(Addr) get_addend(ElfW(Rel)* rel, ElfW(Addr) reloc_addr) {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<typename ElfRelIteratorT>
 | 
					template<typename ElfRelIteratorT>
 | 
				
			||||||
bool soinfo::relocate(ElfRelIteratorT&& rel_iterator, const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
 | 
					bool soinfo::relocate(ElfRelIteratorT&& rel_iterator, const soinfo_list_t& global_group,
 | 
				
			||||||
 | 
					                      const soinfo_list_t& local_group) {
 | 
				
			||||||
  for (size_t idx = 0; rel_iterator.has_next(); ++idx) {
 | 
					  for (size_t idx = 0; rel_iterator.has_next(); ++idx) {
 | 
				
			||||||
    const auto rel = rel_iterator.next();
 | 
					    const auto rel = rel_iterator.next();
 | 
				
			||||||
    if (rel == nullptr) {
 | 
					    if (rel == nullptr) {
 | 
				
			||||||
@@ -1523,32 +1537,38 @@ bool soinfo::relocate(ElfRelIteratorT&& rel_iterator, const soinfo_list_t& globa
 | 
				
			|||||||
        MARK(rel->r_offset);
 | 
					        MARK(rel->r_offset);
 | 
				
			||||||
        TRACE_TYPE(RELO, "RELO ABS32 %16llx <- %16llx %s\n",
 | 
					        TRACE_TYPE(RELO, "RELO ABS32 %16llx <- %16llx %s\n",
 | 
				
			||||||
                   reloc, (sym_addr + addend), sym_name);
 | 
					                   reloc, (sym_addr + addend), sym_name);
 | 
				
			||||||
        if ((static_cast<ElfW(Addr)>(INT32_MIN) <= (*reinterpret_cast<ElfW(Addr)*>(reloc) + (sym_addr + addend))) &&
 | 
					        {
 | 
				
			||||||
            ((*reinterpret_cast<ElfW(Addr)*>(reloc) + (sym_addr + addend)) <= static_cast<ElfW(Addr)>(UINT32_MAX))) {
 | 
					          const ElfW(Addr) reloc_value = *reinterpret_cast<ElfW(Addr)*>(reloc);
 | 
				
			||||||
 | 
					          const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT32_MIN);
 | 
				
			||||||
 | 
					          const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT32_MAX);
 | 
				
			||||||
 | 
					          if ((min_value <= (reloc_value + (sym_addr + addend))) &&
 | 
				
			||||||
 | 
					              ((reloc_value + (sym_addr + addend)) <= max_value)) {
 | 
				
			||||||
            *reinterpret_cast<ElfW(Addr)*>(reloc) += (sym_addr + addend);
 | 
					            *reinterpret_cast<ElfW(Addr)*>(reloc) += (sym_addr + addend);
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
 | 
					            DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
 | 
				
			||||||
                 (*reinterpret_cast<ElfW(Addr)*>(reloc) + (sym_addr + addend)),
 | 
					                   (reloc_value + (sym_addr + addend)), min_value, max_value);
 | 
				
			||||||
                 static_cast<ElfW(Addr)>(INT32_MIN),
 | 
					 | 
				
			||||||
                 static_cast<ElfW(Addr)>(UINT32_MAX));
 | 
					 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case R_AARCH64_ABS16:
 | 
					      case R_AARCH64_ABS16:
 | 
				
			||||||
        count_relocation(kRelocAbsolute);
 | 
					        count_relocation(kRelocAbsolute);
 | 
				
			||||||
        MARK(rel->r_offset);
 | 
					        MARK(rel->r_offset);
 | 
				
			||||||
        TRACE_TYPE(RELO, "RELO ABS16 %16llx <- %16llx %s\n",
 | 
					        TRACE_TYPE(RELO, "RELO ABS16 %16llx <- %16llx %s\n",
 | 
				
			||||||
                   reloc, (sym_addr + addend), sym_name);
 | 
					                   reloc, (sym_addr + addend), sym_name);
 | 
				
			||||||
        if ((static_cast<ElfW(Addr)>(INT16_MIN) <= (*reinterpret_cast<ElfW(Addr)*>(reloc) + (sym_addr + addend))) &&
 | 
					        {
 | 
				
			||||||
            ((*reinterpret_cast<ElfW(Addr)*>(reloc) + (sym_addr + addend)) <= static_cast<ElfW(Addr)>(UINT16_MAX))) {
 | 
					          const ElfW(Addr) reloc_value = *reinterpret_cast<ElfW(Addr)*>(reloc);
 | 
				
			||||||
 | 
					          const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT16_MIN);
 | 
				
			||||||
 | 
					          const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT16_MAX);
 | 
				
			||||||
 | 
					          if ((min_value <= (reloc_value + (sym_addr + addend))) &&
 | 
				
			||||||
 | 
					              ((reloc_value + (sym_addr + addend)) <= max_value)) {
 | 
				
			||||||
            *reinterpret_cast<ElfW(Addr)*>(reloc) += (sym_addr + addend);
 | 
					            *reinterpret_cast<ElfW(Addr)*>(reloc) += (sym_addr + addend);
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
 | 
					            DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
 | 
				
			||||||
                 (*reinterpret_cast<ElfW(Addr)*>(reloc) + (sym_addr + addend)),
 | 
					                   reloc_value + (sym_addr + addend), min_value, max_value);
 | 
				
			||||||
                 static_cast<ElfW(Addr)>(INT16_MIN),
 | 
					 | 
				
			||||||
                 static_cast<ElfW(Addr)>(UINT16_MAX));
 | 
					 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case R_AARCH64_PREL64:
 | 
					      case R_AARCH64_PREL64:
 | 
				
			||||||
        count_relocation(kRelocRelative);
 | 
					        count_relocation(kRelocRelative);
 | 
				
			||||||
@@ -1562,32 +1582,38 @@ bool soinfo::relocate(ElfRelIteratorT&& rel_iterator, const soinfo_list_t& globa
 | 
				
			|||||||
        MARK(rel->r_offset);
 | 
					        MARK(rel->r_offset);
 | 
				
			||||||
        TRACE_TYPE(RELO, "RELO REL32 %16llx <- %16llx - %16llx %s\n",
 | 
					        TRACE_TYPE(RELO, "RELO REL32 %16llx <- %16llx - %16llx %s\n",
 | 
				
			||||||
                   reloc, (sym_addr + addend), rel->r_offset, sym_name);
 | 
					                   reloc, (sym_addr + addend), rel->r_offset, sym_name);
 | 
				
			||||||
        if ((static_cast<ElfW(Addr)>(INT32_MIN) <= (*reinterpret_cast<ElfW(Addr)*>(reloc) + ((sym_addr + addend) - rel->r_offset))) &&
 | 
					        {
 | 
				
			||||||
            ((*reinterpret_cast<ElfW(Addr)*>(reloc) + ((sym_addr + addend) - rel->r_offset)) <= static_cast<ElfW(Addr)>(UINT32_MAX))) {
 | 
					          const ElfW(Addr) reloc_value = *reinterpret_cast<ElfW(Addr)*>(reloc);
 | 
				
			||||||
 | 
					          const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT32_MIN);
 | 
				
			||||||
 | 
					          const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT32_MAX);
 | 
				
			||||||
 | 
					          if ((min_value <= (reloc_value + ((sym_addr + addend) - rel->r_offset))) &&
 | 
				
			||||||
 | 
					              ((reloc_value + ((sym_addr + addend) - rel->r_offset)) <= max_value)) {
 | 
				
			||||||
            *reinterpret_cast<ElfW(Addr)*>(reloc) += ((sym_addr + addend) - rel->r_offset);
 | 
					            *reinterpret_cast<ElfW(Addr)*>(reloc) += ((sym_addr + addend) - rel->r_offset);
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
 | 
					            DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
 | 
				
			||||||
                 (*reinterpret_cast<ElfW(Addr)*>(reloc) + ((sym_addr + addend) - rel->r_offset)),
 | 
					                   reloc_value + ((sym_addr + addend) - rel->r_offset), min_value, max_value);
 | 
				
			||||||
                 static_cast<ElfW(Addr)>(INT32_MIN),
 | 
					 | 
				
			||||||
                 static_cast<ElfW(Addr)>(UINT32_MAX));
 | 
					 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case R_AARCH64_PREL16:
 | 
					      case R_AARCH64_PREL16:
 | 
				
			||||||
        count_relocation(kRelocRelative);
 | 
					        count_relocation(kRelocRelative);
 | 
				
			||||||
        MARK(rel->r_offset);
 | 
					        MARK(rel->r_offset);
 | 
				
			||||||
        TRACE_TYPE(RELO, "RELO REL16 %16llx <- %16llx - %16llx %s\n",
 | 
					        TRACE_TYPE(RELO, "RELO REL16 %16llx <- %16llx - %16llx %s\n",
 | 
				
			||||||
                   reloc, (sym_addr + addend), rel->r_offset, sym_name);
 | 
					                   reloc, (sym_addr + addend), rel->r_offset, sym_name);
 | 
				
			||||||
        if ((static_cast<ElfW(Addr)>(INT16_MIN) <= (*reinterpret_cast<ElfW(Addr)*>(reloc) + ((sym_addr + addend) - rel->r_offset))) &&
 | 
					        {
 | 
				
			||||||
            ((*reinterpret_cast<ElfW(Addr)*>(reloc) + ((sym_addr + addend) - rel->r_offset)) <= static_cast<ElfW(Addr)>(UINT16_MAX))) {
 | 
					          const ElfW(Addr) reloc_value = *reinterpret_cast<ElfW(Addr)*>(reloc);
 | 
				
			||||||
 | 
					          const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT16_MIN);
 | 
				
			||||||
 | 
					          const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT16_MAX);
 | 
				
			||||||
 | 
					          if ((min_value <= (reloc_value + ((sym_addr + addend) - rel->r_offset))) &&
 | 
				
			||||||
 | 
					              ((reloc_value + ((sym_addr + addend) - rel->r_offset)) <= max_value)) {
 | 
				
			||||||
            *reinterpret_cast<ElfW(Addr)*>(reloc) += ((sym_addr + addend) - rel->r_offset);
 | 
					            *reinterpret_cast<ElfW(Addr)*>(reloc) += ((sym_addr + addend) - rel->r_offset);
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
 | 
					            DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
 | 
				
			||||||
                 (*reinterpret_cast<ElfW(Addr)*>(reloc) + ((sym_addr + addend) - rel->r_offset)),
 | 
					                   reloc_value + ((sym_addr + addend) - rel->r_offset), min_value, max_value);
 | 
				
			||||||
                 static_cast<ElfW(Addr)>(INT16_MIN),
 | 
					 | 
				
			||||||
                 static_cast<ElfW(Addr)>(UINT16_MAX));
 | 
					 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case R_AARCH64_COPY:
 | 
					      case R_AARCH64_COPY:
 | 
				
			||||||
@@ -1683,7 +1709,8 @@ bool soinfo::relocate(ElfRelIteratorT&& rel_iterator, const soinfo_list_t& globa
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#endif  // !defined(__mips__)
 | 
					#endif  // !defined(__mips__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void soinfo::call_array(const char* array_name __unused, linker_function_t* functions, size_t count, bool reverse) {
 | 
					void soinfo::call_array(const char* array_name __unused, linker_function_t* functions,
 | 
				
			||||||
 | 
					                        size_t count, bool reverse) {
 | 
				
			||||||
  if (functions == nullptr) {
 | 
					  if (functions == nullptr) {
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -2056,10 +2083,12 @@ bool soinfo::prelink_image() {
 | 
				
			|||||||
        gnu_bloom_filter_ = reinterpret_cast<ElfW(Addr)*>(load_bias + d->d_un.d_ptr + 16);
 | 
					        gnu_bloom_filter_ = reinterpret_cast<ElfW(Addr)*>(load_bias + d->d_un.d_ptr + 16);
 | 
				
			||||||
        gnu_bucket_ = reinterpret_cast<uint32_t*>(gnu_bloom_filter_ + gnu_maskwords_);
 | 
					        gnu_bucket_ = reinterpret_cast<uint32_t*>(gnu_bloom_filter_ + gnu_maskwords_);
 | 
				
			||||||
        // amend chain for symndx = header[1]
 | 
					        // amend chain for symndx = header[1]
 | 
				
			||||||
        gnu_chain_ = gnu_bucket_ + gnu_nbucket_ - reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];
 | 
					        gnu_chain_ = gnu_bucket_ + gnu_nbucket_ -
 | 
				
			||||||
 | 
					            reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!powerof2(gnu_maskwords_)) {
 | 
					        if (!powerof2(gnu_maskwords_)) {
 | 
				
			||||||
          DL_ERR("invalid maskwords for gnu_hash = 0x%x, in \"%s\" expecting power to two", gnu_maskwords_, name);
 | 
					          DL_ERR("invalid maskwords for gnu_hash = 0x%x, in \"%s\" expecting power to two",
 | 
				
			||||||
 | 
					              gnu_maskwords_, name);
 | 
				
			||||||
          return false;
 | 
					          return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        --gnu_maskwords_;
 | 
					        --gnu_maskwords_;
 | 
				
			||||||
@@ -2316,7 +2345,8 @@ bool soinfo::prelink_image() {
 | 
				
			|||||||
      case DT_MIPS_RLD_MAP2:
 | 
					      case DT_MIPS_RLD_MAP2:
 | 
				
			||||||
        // Set the DT_MIPS_RLD_MAP2 entry to the address of _r_debug for GDB.
 | 
					        // Set the DT_MIPS_RLD_MAP2 entry to the address of _r_debug for GDB.
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          r_debug** dp = reinterpret_cast<r_debug**>(reinterpret_cast<ElfW(Addr)>(d) + d->d_un.d_val);
 | 
					          r_debug** dp = reinterpret_cast<r_debug**>(
 | 
				
			||||||
 | 
					              reinterpret_cast<ElfW(Addr)>(d) + d->d_un.d_val);
 | 
				
			||||||
          *dp = &_r_debug;
 | 
					          *dp = &_r_debug;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -238,7 +238,8 @@ struct soinfo {
 | 
				
			|||||||
  void call_destructors();
 | 
					  void call_destructors();
 | 
				
			||||||
  void call_pre_init_constructors();
 | 
					  void call_pre_init_constructors();
 | 
				
			||||||
  bool prelink_image();
 | 
					  bool prelink_image();
 | 
				
			||||||
  bool link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group, const android_dlextinfo* extinfo);
 | 
					  bool link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group,
 | 
				
			||||||
 | 
					                  const android_dlextinfo* extinfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void add_child(soinfo* child);
 | 
					  void add_child(soinfo* child);
 | 
				
			||||||
  void remove_all_links();
 | 
					  void remove_all_links();
 | 
				
			||||||
@@ -289,7 +290,8 @@ struct soinfo {
 | 
				
			|||||||
  void call_array(const char* array_name, linker_function_t* functions, size_t count, bool reverse);
 | 
					  void call_array(const char* array_name, linker_function_t* functions, size_t count, bool reverse);
 | 
				
			||||||
  void call_function(const char* function_name, linker_function_t function);
 | 
					  void call_function(const char* function_name, linker_function_t function);
 | 
				
			||||||
  template<typename ElfRelIteratorT>
 | 
					  template<typename ElfRelIteratorT>
 | 
				
			||||||
  bool relocate(ElfRelIteratorT&& rel_iterator, const soinfo_list_t& global_group, const soinfo_list_t& local_group);
 | 
					  bool relocate(ElfRelIteratorT&& rel_iterator, const soinfo_list_t& global_group,
 | 
				
			||||||
 | 
					                const soinfo_list_t& local_group);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 private:
 | 
					 private:
 | 
				
			||||||
  // This part of the structure is only available
 | 
					  // This part of the structure is only available
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,7 +47,9 @@ template bool soinfo::relocate<packed_reloc_iterator<leb128_decoder>>(
 | 
				
			|||||||
    const soinfo_list_t& local_group);
 | 
					    const soinfo_list_t& local_group);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <typename ElfRelIteratorT>
 | 
					template <typename ElfRelIteratorT>
 | 
				
			||||||
bool soinfo::relocate(ElfRelIteratorT&& rel_iterator, const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
 | 
					bool soinfo::relocate(ElfRelIteratorT&& rel_iterator,
 | 
				
			||||||
 | 
					                      const soinfo_list_t& global_group,
 | 
				
			||||||
 | 
					                      const soinfo_list_t& local_group) {
 | 
				
			||||||
  for (size_t idx = 0; rel_iterator.has_next(); ++idx) {
 | 
					  for (size_t idx = 0; rel_iterator.has_next(); ++idx) {
 | 
				
			||||||
    const auto rel = rel_iterator.next();
 | 
					    const auto rel = rel_iterator.next();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -115,7 +117,8 @@ bool soinfo::relocate(ElfRelIteratorT&& rel_iterator, const soinfo_list_t& globa
 | 
				
			|||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool soinfo::mips_relocate_got(const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
 | 
					bool soinfo::mips_relocate_got(const soinfo_list_t& global_group,
 | 
				
			||||||
 | 
					                               const soinfo_list_t& local_group) {
 | 
				
			||||||
  ElfW(Addr)** got = plt_got_;
 | 
					  ElfW(Addr)** got = plt_got_;
 | 
				
			||||||
  if (got == nullptr) {
 | 
					  if (got == nullptr) {
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -240,7 +240,8 @@ bool ElfReader::ReadProgramHeader() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  phdr_size_ = page_max - page_min;
 | 
					  phdr_size_ = page_max - page_min;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void* mmap_result = mmap64(nullptr, phdr_size_, PROT_READ, MAP_PRIVATE, fd_, file_offset_ + page_min);
 | 
					  void* mmap_result =
 | 
				
			||||||
 | 
					      mmap64(nullptr, phdr_size_, PROT_READ, MAP_PRIVATE, fd_, file_offset_ + page_min);
 | 
				
			||||||
  if (mmap_result == MAP_FAILED) {
 | 
					  if (mmap_result == MAP_FAILED) {
 | 
				
			||||||
    DL_ERR("\"%s\" phdr mmap failed: %s", name_, strerror(errno));
 | 
					    DL_ERR("\"%s\" phdr mmap failed: %s", name_, strerror(errno));
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
@@ -449,7 +450,8 @@ static int _phdr_table_set_load_prot(const ElfW(Phdr)* phdr_table, size_t phdr_c
 | 
				
			|||||||
 * Return:
 | 
					 * Return:
 | 
				
			||||||
 *   0 on error, -1 on failure (error code in errno).
 | 
					 *   0 on error, -1 on failure (error code in errno).
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias) {
 | 
					int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table,
 | 
				
			||||||
 | 
					                                size_t phdr_count, ElfW(Addr) load_bias) {
 | 
				
			||||||
  return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, 0);
 | 
					  return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -469,7 +471,8 @@ int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count,
 | 
				
			|||||||
 * Return:
 | 
					 * Return:
 | 
				
			||||||
 *   0 on error, -1 on failure (error code in errno).
 | 
					 *   0 on error, -1 on failure (error code in errno).
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias) {
 | 
					int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table,
 | 
				
			||||||
 | 
					                                  size_t phdr_count, ElfW(Addr) load_bias) {
 | 
				
			||||||
  return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, PROT_WRITE);
 | 
					  return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, PROT_WRITE);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -531,7 +534,8 @@ static int _phdr_table_set_gnu_relro_prot(const ElfW(Phdr)* phdr_table, size_t p
 | 
				
			|||||||
 * Return:
 | 
					 * Return:
 | 
				
			||||||
 *   0 on error, -1 on failure (error code in errno).
 | 
					 *   0 on error, -1 on failure (error code in errno).
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias) {
 | 
					int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table,
 | 
				
			||||||
 | 
					                                 size_t phdr_count, ElfW(Addr) load_bias) {
 | 
				
			||||||
  return _phdr_table_set_gnu_relro_prot(phdr_table, phdr_count, load_bias, PROT_READ);
 | 
					  return _phdr_table_set_gnu_relro_prot(phdr_table, phdr_count, load_bias, PROT_READ);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -547,7 +551,9 @@ int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count
 | 
				
			|||||||
 * Return:
 | 
					 * Return:
 | 
				
			||||||
 *   0 on error, -1 on failure (error code in errno).
 | 
					 *   0 on error, -1 on failure (error code in errno).
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
 | 
					int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table,
 | 
				
			||||||
 | 
					                                   size_t phdr_count,
 | 
				
			||||||
 | 
					                                   ElfW(Addr) load_bias,
 | 
				
			||||||
                                   int fd) {
 | 
					                                   int fd) {
 | 
				
			||||||
  const ElfW(Phdr)* phdr = phdr_table;
 | 
					  const ElfW(Phdr)* phdr = phdr_table;
 | 
				
			||||||
  const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
 | 
					  const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
 | 
				
			||||||
@@ -592,7 +598,9 @@ int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_cou
 | 
				
			|||||||
 * Return:
 | 
					 * Return:
 | 
				
			||||||
 *   0 on error, -1 on failure (error code in errno).
 | 
					 *   0 on error, -1 on failure (error code in errno).
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
 | 
					int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table,
 | 
				
			||||||
 | 
					                             size_t phdr_count,
 | 
				
			||||||
 | 
					                             ElfW(Addr) load_bias,
 | 
				
			||||||
                             int fd) {
 | 
					                             int fd) {
 | 
				
			||||||
  // Map the file at a temporary location so we can compare its contents.
 | 
					  // Map the file at a temporary location so we can compare its contents.
 | 
				
			||||||
  struct stat file_stat;
 | 
					  struct stat file_stat;
 | 
				
			||||||
@@ -725,11 +733,12 @@ void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_co
 | 
				
			|||||||
                                    ElfW(Addr) load_bias, ElfW(Dyn)** dynamic,
 | 
					                                    ElfW(Addr) load_bias, ElfW(Dyn)** dynamic,
 | 
				
			||||||
                                    ElfW(Word)* dynamic_flags) {
 | 
					                                    ElfW(Word)* dynamic_flags) {
 | 
				
			||||||
  *dynamic = nullptr;
 | 
					  *dynamic = nullptr;
 | 
				
			||||||
  for (const ElfW(Phdr)* phdr = phdr_table, *phdr_limit = phdr + phdr_count; phdr < phdr_limit; phdr++) {
 | 
					  for (size_t i = 0; i<phdr_count; ++i) {
 | 
				
			||||||
    if (phdr->p_type == PT_DYNAMIC) {
 | 
					    const ElfW(Phdr)& phdr = phdr_table[i];
 | 
				
			||||||
      *dynamic = reinterpret_cast<ElfW(Dyn)*>(load_bias + phdr->p_vaddr);
 | 
					    if (phdr.p_type == PT_DYNAMIC) {
 | 
				
			||||||
 | 
					      *dynamic = reinterpret_cast<ElfW(Dyn)*>(load_bias + phdr.p_vaddr);
 | 
				
			||||||
      if (dynamic_flags) {
 | 
					      if (dynamic_flags) {
 | 
				
			||||||
        *dynamic_flags = phdr->p_flags;
 | 
					        *dynamic_flags = phdr.p_flags;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -84,17 +84,20 @@ class ElfReader {
 | 
				
			|||||||
size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count,
 | 
					size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count,
 | 
				
			||||||
                                ElfW(Addr)* min_vaddr = nullptr, ElfW(Addr)* max_vaddr = nullptr);
 | 
					                                ElfW(Addr)* min_vaddr = nullptr, ElfW(Addr)* max_vaddr = nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias);
 | 
					int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table,
 | 
				
			||||||
 | 
					                                size_t phdr_count, ElfW(Addr) load_bias);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias);
 | 
					int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count,
 | 
				
			||||||
 | 
					                                  ElfW(Addr) load_bias);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias);
 | 
					int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count,
 | 
				
			||||||
 | 
					                                 ElfW(Addr) load_bias);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
 | 
					int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count,
 | 
				
			||||||
                                   int fd);
 | 
					                                   ElfW(Addr) load_bias, int fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
 | 
					int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count,
 | 
				
			||||||
                             int fd);
 | 
					                             ElfW(Addr) load_bias, int fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(__arm__)
 | 
					#if defined(__arm__)
 | 
				
			||||||
int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
 | 
					int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,15 +21,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define RELOCATION_GROUPED_BY_INFO_FLAG 1
 | 
					const size_t RELOCATION_GROUPED_BY_INFO_FLAG = 1;
 | 
				
			||||||
#define RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG 2
 | 
					const size_t RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG = 2;
 | 
				
			||||||
#define RELOCATION_GROUPED_BY_ADDEND_FLAG 4
 | 
					const size_t RELOCATION_GROUPED_BY_ADDEND_FLAG = 4;
 | 
				
			||||||
#define RELOCATION_GROUP_HAS_ADDEND_FLAG 8
 | 
					const size_t RELOCATION_GROUP_HAS_ADDEND_FLAG = 8;
 | 
				
			||||||
 | 
					 | 
				
			||||||
#define RELOCATION_GROUPED_BY_INFO(flags) (((flags) & RELOCATION_GROUPED_BY_INFO_FLAG) != 0)
 | 
					 | 
				
			||||||
#define RELOCATION_GROUPED_BY_OFFSET_DELTA(flags) (((flags) & RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG) != 0)
 | 
					 | 
				
			||||||
#define RELOCATION_GROUPED_BY_ADDEND(flags) (((flags) & RELOCATION_GROUPED_BY_ADDEND_FLAG) != 0)
 | 
					 | 
				
			||||||
#define RELOCATION_GROUP_HAS_ADDEND(flags) (((flags) & RELOCATION_GROUP_HAS_ADDEND_FLAG) != 0)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class plain_reloc_iterator {
 | 
					class plain_reloc_iterator {
 | 
				
			||||||
#if defined(USE_RELA)
 | 
					#if defined(USE_RELA)
 | 
				
			||||||
@@ -89,18 +84,19 @@ class packed_reloc_iterator {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (RELOCATION_GROUPED_BY_OFFSET_DELTA(group_flags_)) {
 | 
					    if (is_relocation_grouped_by_offset_delta()) {
 | 
				
			||||||
      reloc_.r_offset += group_r_offset_delta_;
 | 
					      reloc_.r_offset += group_r_offset_delta_;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      reloc_.r_offset += decoder_.pop_front();
 | 
					      reloc_.r_offset += decoder_.pop_front();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!RELOCATION_GROUPED_BY_INFO(group_flags_)) {
 | 
					    if (!is_relocation_grouped_by_info()) {
 | 
				
			||||||
      reloc_.r_info = decoder_.pop_front();
 | 
					      reloc_.r_info = decoder_.pop_front();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(USE_RELA)
 | 
					#if defined(USE_RELA)
 | 
				
			||||||
    if (RELOCATION_GROUP_HAS_ADDEND(group_flags_) && !RELOCATION_GROUPED_BY_ADDEND(group_flags_)) {
 | 
					    if (is_relocation_group_has_addend() &&
 | 
				
			||||||
 | 
					        !is_relocation_grouped_by_addend()) {
 | 
				
			||||||
      reloc_.r_addend += decoder_.pop_front();
 | 
					      reloc_.r_addend += decoder_.pop_front();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -115,22 +111,23 @@ class packed_reloc_iterator {
 | 
				
			|||||||
    group_size_ = decoder_.pop_front();
 | 
					    group_size_ = decoder_.pop_front();
 | 
				
			||||||
    group_flags_ = decoder_.pop_front();
 | 
					    group_flags_ = decoder_.pop_front();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (RELOCATION_GROUPED_BY_OFFSET_DELTA(group_flags_)) {
 | 
					    if (is_relocation_grouped_by_offset_delta()) {
 | 
				
			||||||
      group_r_offset_delta_ = decoder_.pop_front();
 | 
					      group_r_offset_delta_ = decoder_.pop_front();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (RELOCATION_GROUPED_BY_INFO(group_flags_)) {
 | 
					    if (is_relocation_grouped_by_info()) {
 | 
				
			||||||
      reloc_.r_info = decoder_.pop_front();
 | 
					      reloc_.r_info = decoder_.pop_front();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (RELOCATION_GROUP_HAS_ADDEND(group_flags_) && RELOCATION_GROUPED_BY_ADDEND(group_flags_)) {
 | 
					    if (is_relocation_group_has_addend() &&
 | 
				
			||||||
 | 
					        is_relocation_grouped_by_addend()) {
 | 
				
			||||||
#if !defined(USE_RELA)
 | 
					#if !defined(USE_RELA)
 | 
				
			||||||
      // This platform does not support rela, and yet we have it encoded in android_rel section.
 | 
					      // This platform does not support rela, and yet we have it encoded in android_rel section.
 | 
				
			||||||
      DL_ERR("unexpected r_addend in android.rel section");
 | 
					      DL_ERR("unexpected r_addend in android.rel section");
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
      reloc_.r_addend += decoder_.pop_front();
 | 
					      reloc_.r_addend += decoder_.pop_front();
 | 
				
			||||||
    } else if (!RELOCATION_GROUP_HAS_ADDEND(group_flags_)) {
 | 
					    } else if (!is_relocation_group_has_addend()) {
 | 
				
			||||||
      reloc_.r_addend = 0;
 | 
					      reloc_.r_addend = 0;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -139,6 +136,22 @@ class packed_reloc_iterator {
 | 
				
			|||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool is_relocation_grouped_by_info() {
 | 
				
			||||||
 | 
					    return (group_flags_ & RELOCATION_GROUPED_BY_INFO_FLAG) != 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool is_relocation_grouped_by_offset_delta() {
 | 
				
			||||||
 | 
					    return (group_flags_ & RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG) != 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool is_relocation_grouped_by_addend() {
 | 
				
			||||||
 | 
					    return (group_flags_ & RELOCATION_GROUPED_BY_ADDEND_FLAG) != 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool is_relocation_group_has_addend() {
 | 
				
			||||||
 | 
					    return (group_flags_ & RELOCATION_GROUP_HAS_ADDEND_FLAG) != 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  decoder_t decoder_;
 | 
					  decoder_t decoder_;
 | 
				
			||||||
  size_t relocation_count_;
 | 
					  size_t relocation_count_;
 | 
				
			||||||
  size_t group_size_;
 | 
					  size_t group_size_;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user