Run constructors before resolving ifunc functions

Bug: 17177284
Change-Id: I5714b9bc2d1ca8f8711806bfb68da3d524213e99
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 8a7c073..e88195f 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -466,14 +466,17 @@
   return NULL;
 }
 
-static void resolve_ifunc_symbols(soinfo* si) {
+void soinfo::resolve_ifunc_symbols() {
+  if (!get_has_ifuncs()) {
+    return;
+  }
 
-  phdr_table_unprotect_segments(si->phdr, si->phnum, si->load_bias);
+  phdr_table_unprotect_segments(phdr, phnum, load_bias);
 
   TRACE_TYPE(IFUNC, "CHECKING FOR IFUNCS AND PERFORMING SYMBOL UPDATES");
 
-  for (size_t i = 0; i < si->nchain; ++i) {
-    ElfW(Sym)* s = &si->symtab[i];
+  for (size_t i = 0; i < nchain; ++i) {
+    ElfW(Sym)* s = &symtab[i];
     if (ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC) {
       // The address of the ifunc in the symbol table is the address of the
       // function that chooses the function to which the ifunc will refer.
@@ -481,12 +484,12 @@
       // in the linker and then return its result (minus the base offset).
       TRACE_TYPE(IFUNC, "FOUND IFUNC");
       ElfW(Addr) (*ifunc_ptr)();
-      ifunc_ptr = reinterpret_cast<ElfW(Addr)(*)()>(s->st_value + si->base);
-      s->st_value = (ifunc_ptr() - si->base);
+      ifunc_ptr = reinterpret_cast<ElfW(Addr)(*)()>(s->st_value + base);
+      s->st_value = (ifunc_ptr() - base);
       TRACE_TYPE(IFUNC, "NEW VALUE IS %p", (void*)s->st_value);
     }
   }
-  phdr_table_protect_segments(si->phdr, si->phnum, si->load_bias);
+  phdr_table_protect_segments(phdr, phnum, load_bias);
 }
 
 static unsigned elfhash(const char* _name) {
@@ -809,10 +812,6 @@
       return NULL;
     }
 
-    // if the library has any ifuncs, we will need to resolve them so that dlsym
-    // can handle them properly
-    resolve_ifunc_symbols(si);
-
     return si;
 }
 
@@ -1567,6 +1566,8 @@
   // DT_INIT should be called before DT_INIT_ARRAY if both are present.
   CallFunction("DT_INIT", init_func);
   CallArray("DT_INIT_ARRAY", init_array, init_array_count, false);
+
+  resolve_ifunc_symbols();
 }
 
 void soinfo::CallDestructors() {