diff options
author | Dan Albert <danalbert@google.com> | 2019-02-21 21:14:09 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2019-02-21 21:14:09 +0000 |
commit | 5e15f34c504b1b03b7c5285496e8ba4b4a4831a9 (patch) | |
tree | 7d9d3bdf1ba5bf581f5b91a8eff4d72153371df1 | |
parent | 7cdbd0d477176e0973beb7328e40c328aa73d1e5 (diff) | |
parent | a535d3ca6557ced23d8f87d1b3f6b85bd2e8e068 (diff) | |
download | bionic-5e15f34c504b1b03b7c5285496e8ba4b4a4831a9.tar.gz |
Merge "Make static ifunc resolvers optional."ndk-r20bndk-r20-beta3ndk-r20-beta2ndk-r20-beta1ndk-r20ndk-release-r20
-rw-r--r-- | libc/bionic/libc_init_static.cpp | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp index 3219239b7..41f100dbb 100644 --- a/libc/bionic/libc_init_static.cpp +++ b/libc/bionic/libc_init_static.cpp @@ -67,9 +67,20 @@ static void call_array(void(**list)()) { } #if defined(__aarch64__) || defined(__x86_64__) -extern __LIBC_HIDDEN__ ElfW(Rela) __rela_iplt_start[], __rela_iplt_end[]; +extern __LIBC_HIDDEN__ __attribute__((weak)) ElfW(Rela) __rela_iplt_start[], __rela_iplt_end[]; static void call_ifunc_resolvers() { + if (__rela_iplt_start == nullptr || __rela_iplt_end == nullptr) { + // These symbols are not emitted by gold. Gold has code to do so, but for + // whatever reason it is not being run. In these cases ifuncs cannot be + // resolved, so we do not support using ifuncs in static executables linked + // with gold. + // + // Since they are weak, they will be non-null when linked with bfd/lld and + // null when linked with gold. + return; + } + typedef ElfW(Addr) (*ifunc_resolver_t)(void); for (ElfW(Rela) *r = __rela_iplt_start; r != __rela_iplt_end; ++r) { ElfW(Addr)* offset = reinterpret_cast<ElfW(Addr)*>(r->r_offset); @@ -78,9 +89,20 @@ static void call_ifunc_resolvers() { } } #else -extern __LIBC_HIDDEN__ ElfW(Rel) __rel_iplt_start[], __rel_iplt_end[]; +extern __LIBC_HIDDEN__ __attribute__((weak)) ElfW(Rel) __rel_iplt_start[], __rel_iplt_end[]; static void call_ifunc_resolvers() { + if (__rel_iplt_start == nullptr || __rel_iplt_end == nullptr) { + // These symbols are not emitted by gold. Gold has code to do so, but for + // whatever reason it is not being run. In these cases ifuncs cannot be + // resolved, so we do not support using ifuncs in static executables linked + // with gold. + // + // Since they are weak, they will be non-null when linked with bfd/lld and + // null when linked with gold. + return; + } + typedef ElfW(Addr) (*ifunc_resolver_t)(void); for (ElfW(Rel) *r = __rel_iplt_start; r != __rel_iplt_end; ++r) { ElfW(Addr)* offset = reinterpret_cast<ElfW(Addr)*>(r->r_offset); |