Merge "linker: simplify how warnings turn into errors past a certain api level." into main
diff --git a/libc/include/dlfcn.h b/libc/include/dlfcn.h
index 81045fd..dc5b7bb 100644
--- a/libc/include/dlfcn.h
+++ b/libc/include/dlfcn.h
@@ -63,6 +63,22 @@
  * [dlopen(3)](https://man7.org/linux/man-pages/man3/dlopen.3.html)
  * loads the given shared library.
  *
+ * See also
+ * [Android changes for NDK developers](https://android.googlesource.com/platform/bionic/+/main/android-changes-for-ndk-developers.md)
+ * which should cover all dynamic linker behavioral changes relevant to app development.
+ * It also explains how to debug issues with shared libraries on Android
+ * using the `debug.ld.app.*` system properties.
+ *
+ * One Android-specific extension is particularly noteworthy.
+ * The "my_zip_file.zip!/libs/libstuff.so" syntax to load a library
+ * directly from an arbitrary zip file, including but not limited to your apk
+ * (where this is how `extractNativeLibs=false` is implemented).
+ * Related to that, until API level 36 PackageManager is fussy about what
+ * files `extractNativeLibs` will actually extract.
+ * To be compatible with all API levels,
+ * always give files that need to be extracted a "lib" prefix and ".so" suffix,
+ * or avoid using `extractNativeLibs`.
+ *
  * See also android_dlopen_ext().
  *
  * Returns a pointer to an opaque handle for use with other <dlfcn.h> functions
diff --git a/linker/linker.cpp b/linker/linker.cpp
index c42712a..5b200eb 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1099,15 +1099,6 @@
   return dt_needed;
 }
 
-template<typename F>
-static void for_each_dt_needed(const ElfReader& elf_reader, F action) {
-  for (const ElfW(Dyn)* d = elf_reader.dynamic(); d->d_tag != DT_NULL; ++d) {
-    if (d->d_tag == DT_NEEDED) {
-      action(fix_dt_needed(elf_reader.get_string(d->d_un.d_val), elf_reader.name()));
-    }
-  }
-}
-
 static bool find_loaded_library_by_inode(android_namespace_t* ns,
                                          const struct stat& file_stat,
                                          off64_t file_offset,
@@ -1305,11 +1296,14 @@
   }
 #endif
 
-  for_each_dt_needed(task->get_elf_reader(), [&](const char* name) {
-    LD_LOG(kLogDlopen, "load_library(ns=%s, task=%s): Adding DT_NEEDED task: %s",
-           ns->get_name(), task->get_name(), name);
-    load_tasks->push_back(LoadTask::create(name, si, ns, task->get_readers_map()));
-  });
+  for (const ElfW(Dyn)* d = elf_reader.dynamic(); d->d_tag != DT_NULL; ++d) {
+    if (d->d_tag == DT_NEEDED) {
+      const char* name = fix_dt_needed(elf_reader.get_string(d->d_un.d_val), elf_reader.name());
+      LD_LOG(kLogDlopen, "load_library(ns=%s, task=%s): Adding DT_NEEDED task: %s",
+             ns->get_name(), task->get_name(), name);
+      load_tasks->push_back(LoadTask::create(name, si, ns, task->get_readers_map()));
+    }
+  }
 
   return true;
 }
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index f65f82d..40f6b9a 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -435,9 +435,12 @@
     ++ld_preloads_count;
   }
 
-  for_each_dt_needed(si, [&](const char* name) {
-    needed_library_name_list.push_back(name);
-  });
+  for (const ElfW(Dyn)* d = si->dynamic; d->d_tag != DT_NULL; ++d) {
+    if (d->d_tag == DT_NEEDED) {
+      const char* name = fix_dt_needed(si->get_string(d->d_un.d_val), si->get_realpath());
+      needed_library_name_list.push_back(name);
+    }
+  }
 
   const char** needed_library_names = &needed_library_name_list[0];
   size_t needed_libraries_count = needed_library_name_list.size();
diff --git a/linker/linker_soinfo.h b/linker/linker_soinfo.h
index 4d02676..37cee50 100644
--- a/linker/linker_soinfo.h
+++ b/linker/linker_soinfo.h
@@ -524,14 +524,5 @@
 
 const char* fix_dt_needed(const char* dt_needed, const char* sopath);
 
-template<typename F>
-void for_each_dt_needed(const soinfo* si, F action) {
-  for (const ElfW(Dyn)* d = si->dynamic; d->d_tag != DT_NULL; ++d) {
-    if (d->d_tag == DT_NEEDED) {
-      action(fix_dt_needed(si->get_string(d->d_un.d_val), si->get_realpath()));
-    }
-  }
-}
-
 const ElfW(Sym)* soinfo_do_lookup(const char* name, const version_info* vi,
                                   soinfo** si_found_in, const SymbolLookupList& lookup_list);