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";
+}