Modernize SHT_RELR support.

Until now we've only supported RELR with our own OS-private-use
constants. Add support for the official numbers (while maintaining
support for the historical numbers).

Add tests to ensure we continue to support both indefinitely.

We can't yet flip the build system over to using the official constants
because the old GNU binutils objcopy we still use in most cases (for the
mini-debug section) only supports the historical constants.

Bug: http://b/147452927
Test: treehugger
Change-Id: If214fce7fade4316115947e90b78ab40864b61f2
This commit is contained in:
Elliott Hughes 2020-01-24 14:36:10 -08:00
parent 5b9cc31442
commit 6663f5525d
7 changed files with 108 additions and 16 deletions

View file

@ -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 `<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.

View file

@ -26,8 +26,7 @@
* SUCH DAMAGE.
*/
#ifndef _ELF_H
#define _ELF_H
#pragma once
#include <sys/cdefs.h>
@ -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

View file

@ -3070,14 +3070,17 @@ bool soinfo::prelink_image() {
#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 @@ 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:

View file

@ -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",

View file

@ -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();
}

View file

@ -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"],
}

31
tests/libs/relr.cpp Normal file
View file

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