diff --git a/android-changes-for-ndk-developers.md b/android-changes-for-ndk-developers.md index 84456f988..a0f3c3c50 100644 --- a/android-changes-for-ndk-developers.md +++ b/android-changes-for-ndk-developers.md @@ -456,3 +456,19 @@ Most apps should be unaffected by this change, but apps that hook or try to detect hooking of C library functions might need to fix their code to cope with IFUNC relocations. The affected functions are from ``, 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 f5b209193..bebaea127 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 @@ -245,13 +244,9 @@ typedef Elf64_Xword Elf64_Relr; /* 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 @@ typedef Elf64_Xword Elf64_Relr; #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 @@ typedef Elf64_Xword Elf64_Relr; #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 57554fb92..8de82d543 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -3070,14 +3070,17 @@ bool soinfo::prelink_image() { #endif case DT_RELR: + case DT_ANDROID_RELR: relr_ = reinterpret_cast(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(d->d_un.d_val)); return false; @@ -3085,7 +3088,8 @@ bool soinfo::prelink_image() { 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 d3769db14..2bfe42bed 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -613,6 +613,8 @@ cc_defaults { "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 d815dba5e..e36883af1 100644 --- a/tests/dlfcn_test.cpp +++ b/tests/dlfcn_test.cpp @@ -1765,3 +1765,13 @@ TEST(dlfcn, segment_gap) { } #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 2ee6c8665..29224f541 100644 --- a/tests/libs/Android.bp +++ b/tests/libs/Android.bp @@ -1497,3 +1497,29 @@ cc_test_library { 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 000000000..7ea07b52d --- /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"; +}