Move dl_unwind_find_exidx from libdl.a to libc.a

arm32 has two special APIs to find exidx exception handling info,
dl_unwind_find_exidx and __gnu_Unwind_Find_exdix. The two functions have
identical behavior and function prototypes. libgcc's arm32 unwinder calls
__gnu_Unwind_Find_exdix, whereas LLVM's libunwind previously called
__gnu_Unwind_Find_exdix, but switched to dl_unwind_find_exidx as a result
of three patches (D30306, D30681, D39468).

In Bionic, for dynamic linking, __gnu_Unwind_Find_exdix in libc.so calls
dl_unwind_find_exidx in libdl.so.

For static executables, though, __gnu_Unwind_Find_exdix in libc.a used the
__exidx_* symbols, while dl_unwind_find_exidx in libdl.a(libdl_static.o)
was a return-0 no-op.

To fix the LLVM unwinder, replace the no-op dl_unwind_find_exidx in
libdl.a with a real function in libc.a(exidx_static.o), and have the GNU
function call the dl function for more consistency with dynamic linking.

dl_iterate_phdr follows a similar pattern, where the function exists in
libc.a and libdl.so (not libc.so or libdl.a).

This change makes unwinding work with an updated libunwind_llvm on arm32,
and it helps to allow unwinding in static executables without libdl.a.

Bug: https://github.com/android/ndk/issues/1094
Bug: http://b/141485154
Test: NDK tests, bionic unit tests
Change-Id: Ieeeb9b39a0e28544e21f9afe6fe51ef10d7c828c
diff --git a/libc/Android.bp b/libc/Android.bp
index 37e0f09..3e2ee1d 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1525,6 +1525,22 @@
     ],
 }
 
+// Versions of dl_iterate_phdr and similar APIs used to lookup unwinding information in a static
+// executable.
+cc_library_static {
+    name: "libc_unwind_static",
+    defaults: ["libc_defaults"],
+    cflags: ["-DLIBC_STATIC"],
+
+    srcs: ["bionic/dl_iterate_phdr_static.cpp"],
+    arch: {
+        // arm32-specific dl_unwind_find_exidx and __gnu_Unwind_Find_exidx APIs
+        arm: {
+            srcs: ["arch-arm/bionic/exidx_static.c"],
+        },
+    },
+}
+
 // ========================================================
 // libc_nomalloc.a
 // ========================================================
@@ -1537,20 +1553,13 @@
 
 cc_library_static {
     name: "libc_nomalloc",
-
     defaults: ["libc_defaults"],
-
-    arch: {
-        arm: {
-            srcs: ["arch-arm/bionic/exidx_static.c"],
-        },
-    },
-
     cflags: ["-DLIBC_STATIC"],
 
     whole_static_libs: [
         "libc_common_static",
         "libc_init_static",
+        "libc_unwind_static",
     ],
 }
 
@@ -1572,7 +1581,6 @@
 filegroup {
     name: "libc_sources_static",
     srcs: [
-        "bionic/dl_iterate_phdr_static.cpp",
         "bionic/malloc_common.cpp",
         "bionic/malloc_limit.cpp",
     ],
@@ -1586,11 +1594,6 @@
     ],
 }
 
-filegroup {
-    name: "libc_sources_static_arm",
-    srcs: [ "arch-arm/bionic/exidx_static.c" ],
-}
-
 // ========================================================
 // libc.a + libc.so
 // ========================================================
@@ -1613,6 +1616,7 @@
         whole_static_libs: [
             "libc_init_static",
             "libc_common_static",
+            "libc_unwind_static",
         ],
     },
     shared: {
@@ -1662,9 +1666,6 @@
                 // special for arm
                 cflags: ["-DCRT_LEGACY_WORKAROUND"],
             },
-            static: {
-                srcs: [":libc_sources_static_arm"],
-            },
 
             // Arm 32 bit does not produce complete exidx unwind information
             // so keep the .debug_frame which is relatively small and does
diff --git a/libc/arch-arm/bionic/exidx_static.c b/libc/arch-arm/bionic/exidx_static.c
index ef3745f..9830c54 100644
--- a/libc/arch-arm/bionic/exidx_static.c
+++ b/libc/arch-arm/bionic/exidx_static.c
@@ -43,7 +43,11 @@
 extern struct exidx_entry __exidx_end;
 extern struct exidx_entry __exidx_start;
 
-_Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr pc __attribute__((unused)), int* pcount) {
+_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc __attribute__((unused)), int* pcount) {
   *pcount = (&__exidx_end - &__exidx_start);
   return (_Unwind_Ptr)&__exidx_start;
 }
+
+_Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr pc, int *pcount) {
+  return dl_unwind_find_exidx(pc, pcount);
+}
diff --git a/libdl/libdl_static.cpp b/libdl/libdl_static.cpp
index 0a36e6f..3bbf963 100644
--- a/libdl/libdl_static.cpp
+++ b/libdl/libdl_static.cpp
@@ -41,9 +41,3 @@
 int dlclose(void* /*handle*/) {
   return -1;
 }
-
-#if defined(__arm__)
-_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr /*pc*/, int* /*pcount*/) {
-  return 0;
-}
-#endif