Fixing app compat issue b/72143978

This is a squash revert of a4a4854 and 1b0f2b4

  Revert "Remove a test for backwards compatibility we no longer support."

  This reverts commit a4a485454a3a117eccdca1113681f770d765d865.

  # This is the commit message #2:

  Revert "Remove obsolete workaround."

  This reverts commit 1b0f2b49d528c90842b4263269d9039d7e07415e.

Bug: 72143978
Bug: 24465209
Test: Tested failing case on sailfish, reverted back all CL's since
Test: 3471433 for b/24465209 and apps open
diff --git a/libc/Android.bp b/libc/Android.bp
index 3ff5c03..5f04e28 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1723,6 +1723,9 @@
 
     arch: {
         arm: {
+            //TODO: This is to work around b/24465209. Remove after root cause is fixed
+            ldflags: ["-Wl,--hash-style=both"],
+
             // Don't re-export new/delete and friends, even if the compiler really wants to.
             version_script: "libc.arm.map",
 
@@ -1753,6 +1756,9 @@
             version_script: "libc.mips64.map",
         },
         x86: {
+            //TODO: This is to work around b/24465209. Remove after root cause is fixed
+            ldflags: ["-Wl,--hash-style=both"],
+
             // Don't re-export new/delete and friends, even if the compiler really wants to.
             version_script: "libc.x86.map",
         },
@@ -1778,8 +1784,10 @@
     system_shared_libs: ["libc"],
     static_libs: ["libasync_safe"],
 
+    //TODO (dimitry): This is to work around b/24465209. Remove after root cause is fixed
     arch: {
         arm: {
+            ldflags: ["-Wl,--hash-style=both"],
             version_script: "libstdc++.arm.map",
         },
         arm64: {
@@ -1792,6 +1800,7 @@
             version_script: "libstdc++.mips64.map",
         },
         x86: {
+            ldflags: ["-Wl,--hash-style=both"],
             version_script: "libstdc++.x86.map",
         },
         x86_64: {
diff --git a/libdl/Android.bp b/libdl/Android.bp
index 041ee26..3889bdb 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -4,10 +4,7 @@
 cc_library_static {
     name: "libdl_static",
 
-    srcs: [
-        "libdl.cpp",
-        "libdl_cfi.cpp",
-    ],
+    srcs: ["libdl.cpp", "libdl_cfi.cpp"],
 
     cflags: [
         "-Wall",
@@ -46,6 +43,7 @@
     arch: {
         arm: {
             version_script: "libdl.arm.map",
+            ldflags: ["-Wl,--hash-style=both"],
         },
         arm64: {
             version_script: "libdl.arm64.map",
@@ -59,6 +57,7 @@
         x86: {
             ldflags: [
                 "-Wl,--exclude-libs=libgcc_eh.a",
+                "-Wl,--hash-style=both",
             ],
             version_script: "libdl.x86.map",
         },
@@ -71,7 +70,7 @@
         whole_static_libs: ["libdl_static"],
     },
     static: {
-        srcs: ["libdl_static.c"],
+        srcs: [ "libdl_static.c" ],
     },
     cflags: [
         "-Wall",
@@ -91,7 +90,7 @@
 
     // This is placeholder library the actual implementation is (currently)
     // provided by the linker.
-    shared_libs: ["ld-android"],
+    shared_libs: [ "ld-android" ],
 
     sanitize: {
         never: true,
diff --git a/libm/Android.bp b/libm/Android.bp
index f7d8a8b..6d6fafa 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -294,6 +294,7 @@
                 ],
             },
             instruction_set: "arm",
+            ldflags: ["-Wl,--hash-style=both"],
             version_script: "libm.arm.map",
         },
 
@@ -420,6 +421,7 @@
                 ],
             },
             local_include_dirs: ["i387"],
+            ldflags: ["-Wl,--hash-style=both"],
             version_script: "libm.x86.map",
         },
 
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index df580a6..000d1f7 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1414,6 +1414,84 @@
 // Bionic specific tests
 #if defined(__BIONIC__)
 
+#if defined(__arm__)
+const llvm::ELF::Elf32_Dyn* to_dynamic_table(const char* p) {
+  return reinterpret_cast<const llvm::ELF::Elf32_Dyn*>(p);
+}
+
+// Duplicate these definitions here because they are android specific
+// note that we cannot include <elf.h> because #defines conflict with
+// enum names provided by LLVM.
+#define DT_ANDROID_REL (llvm::ELF::DT_LOOS + 2)
+#define DT_ANDROID_RELA (llvm::ELF::DT_LOOS + 4)
+
+template<typename ELFT>
+void validate_compatibility_of_native_library(const std::string& path, ELFT* elf) {
+  bool has_elf_hash = false;
+  bool has_android_rel = false;
+  bool has_rel = false;
+  // Find dynamic section and check that DT_HASH and there is no DT_ANDROID_REL
+  for (auto it = elf->section_begin(); it != elf->section_end(); ++it) {
+    const llvm::object::ELFSectionRef& section_ref = *it;
+    if (section_ref.getType() == llvm::ELF::SHT_DYNAMIC) {
+      llvm::StringRef data;
+      ASSERT_TRUE(!it->getContents(data)) << "unable to get SHT_DYNAMIC section data";
+      for (auto d = to_dynamic_table(data.data()); d->d_tag != llvm::ELF::DT_NULL; ++d) {
+        if (d->d_tag == llvm::ELF::DT_HASH) {
+          has_elf_hash = true;
+        } else if (d->d_tag == DT_ANDROID_REL || d->d_tag == DT_ANDROID_RELA) {
+          has_android_rel = true;
+        } else if (d->d_tag == llvm::ELF::DT_REL || d->d_tag == llvm::ELF::DT_RELA) {
+          has_rel = true;
+        }
+      }
+
+      break;
+    }
+  }
+
+  ASSERT_TRUE(has_elf_hash) << path.c_str() << ": missing elf hash (DT_HASH)";
+  ASSERT_TRUE(!has_android_rel) << path.c_str() << ": has packed relocations";
+  ASSERT_TRUE(has_rel) << path.c_str() << ": missing DT_REL/DT_RELA";
+}
+
+void validate_compatibility_of_native_library(const char* soname) {
+  // On the systems with emulation system libraries would be of different
+  // architecture.  Try to use alternate paths first.
+  std::string path = std::string(ALTERNATE_PATH_TO_SYSTEM_LIB) + soname;
+  auto binary_or_error = llvm::object::createBinary(path);
+  if (!binary_or_error) {
+    path = std::string(PATH_TO_SYSTEM_LIB) + soname;
+    binary_or_error = llvm::object::createBinary(path);
+  }
+  ASSERT_FALSE(!binary_or_error);
+
+  llvm::object::Binary* binary = binary_or_error.get().getBinary();
+
+  auto obj = llvm::dyn_cast<llvm::object::ObjectFile>(binary);
+  ASSERT_TRUE(obj != nullptr);
+
+  auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(obj);
+
+  ASSERT_TRUE(elf != nullptr);
+
+  validate_compatibility_of_native_library(path, elf);
+}
+
+// This is a test for app compatibility workaround for arm apps
+// affected by http://b/24465209
+TEST(dlext, compat_elf_hash_and_relocation_tables) {
+  validate_compatibility_of_native_library("libc.so");
+  validate_compatibility_of_native_library("liblog.so");
+  validate_compatibility_of_native_library("libstdc++.so");
+  validate_compatibility_of_native_library("libdl.so");
+  validate_compatibility_of_native_library("libm.so");
+  validate_compatibility_of_native_library("libz.so");
+  validate_compatibility_of_native_library("libjnigraphics.so");
+}
+
+#endif //  defined(__arm__)
+
 TEST(dlfcn, dlopen_invalid_rw_load_segment) {
   const std::string libpath = get_testlib_root() +
                               "/" + kPrebuiltElfDir +