linker: simplify code for dynamic and ARM exidx sections.

This moves the code that determines where the .dynamic and .ARM.exidx
sections are to a single place in soinfo_link_image().

Change-Id: I98adcb440577bed86442349f03f3c629c945efec
diff --git a/linker/linker.c b/linker/linker.c
index c725d02..a3bc171 100644
--- a/linker/linker.c
+++ b/linker/linker.c
@@ -126,10 +126,6 @@
 unsigned bitmask[4096];
 #endif
 
-#ifndef PT_ARM_EXIDX
-#define PT_ARM_EXIDX    0x70000001      /* .ARM.exidx segment */
-#endif
-
 #define HOODLUM(name, ret, ...)                                               \
     ret name __VA_ARGS__                                                      \
     {                                                                         \
@@ -924,10 +920,6 @@
                 mprotect(pbase, len,
                          PFLAGS_TO_PROT(phdr->p_flags) | PROT_WRITE);
             }
-        } else if (phdr->p_type == PT_DYNAMIC) {
-            DEBUG_DUMP_PHDR(phdr, "PT_DYNAMIC", pid);
-            /* this segment contains the dynamic linking information */
-            si->dynamic = (unsigned *)(base + phdr->p_vaddr);
         } else if (phdr->p_type == PT_GNU_RELRO) {
             if (((base + phdr->p_vaddr) >= si->base + si->size)
                     || ((base + phdr->p_vaddr + phdr->p_memsz) > si->base + si->size)
@@ -939,16 +931,6 @@
             }
             si->gnu_relro_start = (Elf32_Addr) (base + phdr->p_vaddr);
             si->gnu_relro_len = (unsigned) phdr->p_memsz;
-        } else {
-#ifdef ANDROID_ARM_LINKER
-            if (phdr->p_type == PT_ARM_EXIDX) {
-                DEBUG_DUMP_PHDR(phdr, "PT_ARM_EXIDX", pid);
-                /* exidx entries (used for stack unwinding) are 8 bytes each.
-                 */
-                si->ARM_exidx = (unsigned *)(base + phdr->p_vaddr);
-                si->ARM_exidx_count = phdr->p_memsz / 8;
-            }
-#endif
         }
 
     }
@@ -1659,6 +1641,20 @@
     DEBUG("%5d si->base = 0x%08x si->flags = 0x%08x\n", pid,
           si->base, si->flags);
 
+    /* Extract dynamic section */
+    si->dynamic = phdr_table_get_dynamic_section(phdr, phnum, base);
+    if (si->dynamic == NULL) {
+        DL_ERR("%5d missing PT_DYNAMIC?!", pid);
+        goto fail;
+    } else {
+        DEBUG("%5d dynamic = %p\n", pid, si->dynamic);
+    }
+
+#ifdef ANDROID_ARM_LINKER
+    (void) phdr_table_get_arm_exidx(phdr, phnum, base,
+                                    &si->ARM_exidx, &si->ARM_exidx_count);
+#endif
+
     if (si->flags & (FLAG_EXE | FLAG_LINKER)) {
         /* Locate the needed program segments (DYNAMIC/ARM_EXIDX) for
          * linkage info if this is the executable or the linker itself.
@@ -1670,14 +1666,6 @@
          */
         si->size = 0;
         for(; phnum > 0; --phnum, ++phdr) {
-#ifdef ANDROID_ARM_LINKER
-            if(phdr->p_type == PT_ARM_EXIDX) {
-                /* exidx entries (used for stack unwinding) are 8 bytes each.
-                 */
-                si->ARM_exidx = (unsigned *)(base + phdr->p_vaddr);
-                si->ARM_exidx_count = phdr->p_memsz / 8;
-            }
-#endif
             if (phdr->p_type == PT_LOAD) {
                 /* For the executable, we use the si->size field only in
                    dl_unwind_find_exidx(), so the meaning of si->size
@@ -1715,16 +1703,6 @@
                              phdr->p_memsz,
                              PFLAGS_TO_PROT(phdr->p_flags) | PROT_WRITE);
                 }
-            } else if (phdr->p_type == PT_DYNAMIC) {
-                if (si->dynamic != (unsigned *)-1) {
-                    DL_ERR("%5d multiple PT_DYNAMIC segments found in '%s'. "
-                          "Segment at 0x%08x, previously one found at 0x%08x",
-                          pid, si->name, base + phdr->p_vaddr,
-                          (unsigned)si->dynamic);
-                    goto fail;
-                }
-                DEBUG_DUMP_PHDR(phdr, "PT_DYNAMIC", pid);
-                si->dynamic = (unsigned *) (base + phdr->p_vaddr);
             } else if (phdr->p_type == PT_GNU_RELRO) {
                 if ((base + phdr->p_vaddr >= si->base + si->size)
                         || ((base + phdr->p_vaddr + phdr->p_memsz) > si->base + si->size)
@@ -1740,13 +1718,6 @@
         }
     }
 
-    if (si->dynamic == (unsigned *)-1) {
-        DL_ERR("%5d missing PT_DYNAMIC?!", pid);
-        goto fail;
-    }
-
-    DEBUG("%5d dynamic = %p\n", pid, si->dynamic);
-
     /* extract useful information from dynamic section */
     for(d = si->dynamic; *d; d++){
         DEBUG("%5d d = %p, d[0] = 0x%08x d[1] = 0x%08x\n", pid, d, d[0], d[1]);