Merge "Disable Android relocation packing in linker." into main
diff --git a/linker/Android.bp b/linker/Android.bp
index f87a92e..e1a5a91 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -334,6 +334,13 @@
         "-Wl,-Bsymbolic",
         "-Wl,--exclude-libs,ALL",
         "-Wl,-soname,ld-android.so",
+        // When the linker applies its own IRELATIVE relocations, it will only read DT_REL[A] and
+        // DT_JMPREL, not DT_ANDROID_REL[A], which can also theoretically contain IRELATIVE
+        // relocations. lld has been taught to not store them there as a bug workaround (see
+        // https://llvm.org/pr86751) but the workaround could be removed at some point in the
+        // future. So we explicitly prevent it from doing so by disabling DT_ANDROID_REL[A] when
+        // linking the linker (DT_RELR cannot encode IRELATIVE relocations).
+        "-Wl,--pack-dyn-relocs=relr",
     ],
 
     // we are going to link libc++_static manually because
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index c9dcfa3..c0a68af 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -647,6 +647,9 @@
     auto *dyn = reinterpret_cast<ElfW(Dyn)*>(ehdr + phdr[i].p_vaddr);
     ElfW(Addr) pltrel = 0, pltrelsz = 0, rel = 0, relsz = 0;
     for (size_t j = 0, size = phdr[i].p_filesz / sizeof(ElfW(Dyn)); j != size; ++j) {
+      // We can't handle IRELATIVE relocations in DT_ANDROID_REL[A].
+      // We disabled DT_ANDROID_REL[A] at build time; verify that it was actually disabled.
+      CHECK(dyn[j].d_tag != DT_ANDROID_REL && dyn[j].d_tag != DT_ANDROID_RELA);
       if (dyn[j].d_tag == DT_JMPREL) {
         pltrel = dyn[j].d_un.d_ptr;
       } else if (dyn[j].d_tag == DT_PLTRELSZ) {