Add IFUNC support for arm64 and IRELATIVE reloc

 There are number of changes in the way IFUNC related relocations are done:
 1. IRELATIVE relocations are now supported for x86/x86_64 and arm64.
 2. IFUNC relocations are now relying on static linker to generate
    them in correct order - this removes necessety of additional
    relocation pass for ifuncs.
 3. Related to 2: rela?.dyn relocations are preformed before .plt ones.
 4. Ifunc are resolved on symbol lookup this approach allowed to avoid
    mprotect(PROT_WRITE) call on r-x program segments.

Bug: 17399706
Bug: 17177284

(cherry picked from commit 9aea164457c269c475592da36b4655d45f55c7bc)

Change-Id: Ie19d900fc203beb93faf8943b0d06d534a6de4ad
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 3024b3c..9801fa1 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -118,7 +118,7 @@
     unsigned bind = ELF_ST_BIND(sym->st_info);
 
     if ((bind == STB_GLOBAL || bind == STB_WEAK) && sym->st_shndx != 0) {
-      return reinterpret_cast<void*>(sym->st_value + found->load_bias);
+      return reinterpret_cast<void*>(found->resolve_symbol_address(sym));
     }
 
     __bionic_format_dlerror("symbol found but not global", symbol);
@@ -148,7 +148,7 @@
   ElfW(Sym)* sym = dladdr_find_symbol(si, addr);
   if (sym != nullptr) {
     info->dli_sname = si->strtab + sym->st_name;
-    info->dli_saddr = reinterpret_cast<void*>(si->load_bias + sym->st_value);
+    info->dli_saddr = reinterpret_cast<void*>(si->resolve_symbol_address(sym));
   }
 
   return 1;