Merge "Modernize SHT_RELR support."
diff --git a/android-changes-for-ndk-developers.md b/android-changes-for-ndk-developers.md
index 84456f9..a0f3c3c 100644
--- a/android-changes-for-ndk-developers.md
+++ b/android-changes-for-ndk-developers.md
@@ -456,3 +456,19 @@
 detect hooking of C library functions might need to fix their code to cope
 with IFUNC relocations. The affected functions are from `<string.h>`, but
 may expand to include more functions (and more libraries) in future.
+
+## Relative relocations (RELR)
+
+Android added experimental support for RELR relative relocations
+in API level 28, but using `SHT_` and `DT_` constants in the space
+reserved for OS private use.
+
+API level 30 added support for ELF files using the official `SHT_` and
+`DT_` constants.
+
+The RELR encoding is unrelated to the earlier "packed relocations"
+format available from API level 23.
+
+There are no plans to remove support for ELF files using the older
+OS private use constants for RELR, nor for ELF files using packed
+relocations.
diff --git a/libc/include/elf.h b/libc/include/elf.h
index f5b2091..bebaea1 100644
--- a/libc/include/elf.h
+++ b/libc/include/elf.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _ELF_H
-#define _ELF_H
+#pragma once
 
 #include <sys/cdefs.h>
 
@@ -245,13 +244,9 @@
 /* glibc and BSD disagree for DT_ENCODING; glibc looks wrong. */
 #define DT_PREINIT_ARRAY 32
 #define DT_PREINIT_ARRAYSZ 33
-
-/* Experimental support for SHT_RELR sections. For details, see proposal
-   at https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg */
-#define DT_RELR 0x6fffe000
-#define DT_RELRSZ 0x6fffe001
-#define DT_RELRENT 0x6fffe003
-#define DT_RELRCOUNT 0x6fffe005
+#define DT_RELRSZ 35
+#define DT_RELR 36
+#define DT_RELRENT 37
 
 /* Android compressed rel/rela sections */
 #define DT_ANDROID_REL (DT_LOOS + 2)
@@ -502,15 +497,12 @@
 #define SHT_PREINIT_ARRAY 16
 #define SHT_GROUP 17
 #define SHT_SYMTAB_SHNDX 18
+#define SHT_RELR 19
 #undef SHT_NUM
-#define SHT_NUM 19
+#define SHT_NUM 20
 #define SHT_LOOS 0x60000000
 #define SHT_HIOS 0x6fffffff
 
-/* Experimental support for SHT_RELR sections. For details, see proposal
-   at https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg */
-#define SHT_RELR 0x6fffff00
-
 /* http://www.sco.com/developers/gabi/latest/ch4.symtab.html */
 #define STN_UNDEF 0
 
@@ -540,4 +532,15 @@
 #define VER_NDX_LOCAL 0
 #define VER_NDX_GLOBAL 1
 
-#endif /* _ELF_H */
+/*
+ * Experimental support for SHT_RELR sections. For details, see proposal
+ * at https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg.
+ * This was eventually replaced by SHT_RELR and DT_RELR (which are identical
+ * other than their different constants), but those constants are only
+ * supported by the OS starting at API level 30.
+ */
+#define SHT_ANDROID_RELR 0x6fffff00
+#define DT_ANDROID_RELR 0x6fffe000
+#define DT_ANDROID_RELRSZ 0x6fffe001
+#define DT_ANDROID_RELRENT 0x6fffe003
+#define DT_ANDROID_RELRCOUNT 0x6fffe005
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 57554fb..8de82d5 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -3070,14 +3070,17 @@
 
 #endif
       case DT_RELR:
+      case DT_ANDROID_RELR:
         relr_ = reinterpret_cast<ElfW(Relr)*>(load_bias + d->d_un.d_ptr);
         break;
 
       case DT_RELRSZ:
+      case DT_ANDROID_RELRSZ:
         relr_count_ = d->d_un.d_val / sizeof(ElfW(Relr));
         break;
 
       case DT_RELRENT:
+      case DT_ANDROID_RELRENT:
         if (d->d_un.d_val != sizeof(ElfW(Relr))) {
           DL_ERR("invalid DT_RELRENT: %zd", static_cast<size_t>(d->d_un.d_val));
           return false;
@@ -3085,7 +3088,8 @@
         break;
 
       // Ignored (see DT_RELCOUNT comments for details).
-      case DT_RELRCOUNT:
+      // There is no DT_RELRCOUNT specifically because it would only be ignored.
+      case DT_ANDROID_RELRCOUNT:
         break;
 
       case DT_INIT:
diff --git a/tests/Android.bp b/tests/Android.bp
index d3769db..2bfe42b 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -613,6 +613,8 @@
         "libdl_preempt_test_2",
         "libdl_test_df_1_global",
         "libgnu-hash-table-library",
+        "librelr-new",
+        "librelr-old",
         "libsysv-hash-table-library",
         "libtestshared",
         "libtest_atexit",
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index d815dba..e36883a 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1765,3 +1765,13 @@
 }
 
 #endif
+
+TEST(dlfcn, relr_old) {
+  void* handle = dlopen("librelr-old.so", RTLD_NOW);
+  ASSERT_TRUE(handle != nullptr) << dlerror();
+}
+
+TEST(dlfcn, relr_new) {
+  void* handle = dlopen("librelr-new.so", RTLD_NOW);
+  ASSERT_TRUE(handle != nullptr) << dlerror();
+}
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 2ee6c86..29224f5 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -1497,3 +1497,29 @@
     defaults: ["bionic_testlib_defaults"],
     srcs: ["segment_gap_inner.cpp"],
 }
+
+
+// -----------------------------------------------------------------------------
+// Check that we support both the old and new SHT_RELR constants.
+// -----------------------------------------------------------------------------
+
+cc_test_library {
+    name: "librelr-new",
+    ldflags: ["-Wl,--no-use-android-relr-tags"],
+    host_supported: false,
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["relr.cpp"],
+    // Hack to ensure we're using llvm-objcopy because our binutils prebuilt
+    // only supports the old numbers (http://b/141010852).
+    strip: {
+      keep_symbols: true,
+    },
+}
+
+cc_test_library {
+    name: "librelr-old",
+    ldflags: ["-Wl,--use-android-relr-tags"],
+    host_supported: false,
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["relr.cpp"],
+}
diff --git a/tests/libs/relr.cpp b/tests/libs/relr.cpp
new file mode 100644
index 0000000..7ea07b5
--- /dev/null
+++ b/tests/libs/relr.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+extern "C" const char* relr() {
+  return "relr";
+}