===================================================================
@@ -28,6 +28,9 @@ endif
ASFLAGS-.os += $(pic-ccflag)
ifeq ($(subdir),elf)
+# Extra shared linker files to link into dl-allobjs.so and libc.
+sysdep-dl-routines += dl-abiflags-cache
+
ifneq ($(o32-fpabi),)
tests += tst-abi-interlink
===================================================================
@@ -0,0 +1,68 @@
+/* MIPS FP ABI cache maintenance.
+ Copyright (C) 2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <elf.h>
+#include <ldsodefs.h>
+#include <link.h>
+#include <stdbool.h>
+
+#include <dl-abiflags-cache.h>
+
+/* Return failure with a debug message. */
+#define FAIL(str, args...) \
+ { \
+ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_LIBS)) \
+ _dl_debug_printf (str, ##args); \
+ return false; \
+ }
+
+/* Cache the FP ABI value from the PT_MIPS_ABIFLAGS program header. */
+
+bool
+internal_function
+__mips_abiflags_cache (struct link_map *l)
+{
+ if (l->l_mach.fpabi == 0)
+ {
+ const ElfW (Phdr) *ph = find_mips_abiflags (l->l_phdr, l->l_phnum);
+
+ if (ph)
+ {
+ Elf_MIPS_ABIFlags_v0 *mips_abiflags;
+ if (ph->p_filesz < sizeof (Elf_MIPS_ABIFlags_v0))
+ FAIL (" %s: malformed PT_MIPS_ABIFLAGS found\n", l->l_name);
+
+ mips_abiflags = (Elf_MIPS_ABIFlags_v0 *) (l->l_addr + ph->p_vaddr);
+
+ if (__glibc_unlikely (mips_abiflags->flags2 != 0))
+ FAIL (" %s: unknown MIPS.abiflags flags2: %u\n", l->l_name,
+ mips_abiflags->flags2);
+
+ l->l_mach.fpabi = mips_abiflags->fp_abi;
+ l->l_mach.odd_spreg = (mips_abiflags->flags1
+ & MIPS_AFL_FLAGS1_ODDSPREG) != 0;
+ }
+ else
+ {
+ l->l_mach.fpabi = -1;
+ l->l_mach.odd_spreg = true;
+ }
+ }
+ return true;
+}
+libc_hidden_def (__mips_abiflags_cache)
===================================================================
@@ -0,0 +1,44 @@
+/* MIPS FP ABI cache maintenance.
+ Copyright (C) 2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _DL_FPABI_CACHE
+#define _DL_FPABI_CACHE 1
+
+#include <elf.h>
+#include <link.h>
+#include <stdbool.h>
+
+/* Search the program headers for the ABI Flags. */
+
+static inline const ElfW (Phdr) *
+find_mips_abiflags (const ElfW (Phdr) *phdr, ElfW (Half) phnum)
+{
+ const ElfW (Phdr) *ph;
+
+ for (ph = phdr; ph < &phdr[phnum]; ++ph)
+ if (ph->p_type == PT_MIPS_ABIFLAGS)
+ return ph;
+ return NULL;
+}
+
+/* Cache the FP ABI value from the PT_MIPS_ABIFLAGS program header. */
+
+extern bool __mips_abiflags_cache (struct link_map *l);
+libc_hidden_proto (__mips_abiflags_cache)
+
+#endif /* dl-abiflags-cache.h */
===================================================================
@@ -22,6 +22,8 @@
#include <unistd.h>
#include <sys/prctl.h>
+#include <dl-abiflags-cache.h>
+
#if defined PR_GET_FP_MODE && defined PR_SET_FP_MODE
# define HAVE_PRCTL_FP_MODE 1
#else
@@ -36,53 +38,6 @@
return true; \
}
-/* Search the program headers for the ABI Flags. */
-
-static inline const ElfW(Phdr) *
-find_mips_abiflags (const ElfW(Phdr) *phdr, ElfW(Half) phnum)
-{
- const ElfW(Phdr) *ph;
-
- for (ph = phdr; ph < &phdr[phnum]; ++ph)
- if (ph->p_type == PT_MIPS_ABIFLAGS)
- return ph;
- return NULL;
-}
-
-/* Cache the FP ABI value from the PT_MIPS_ABIFLAGS program header. */
-
-static bool
-cached_fpabi_reject_phdr_p (struct link_map *l)
-{
- if (l->l_mach.fpabi == 0)
- {
- const ElfW(Phdr) *ph = find_mips_abiflags (l->l_phdr, l->l_phnum);
-
- if (ph)
- {
- Elf_MIPS_ABIFlags_v0 * mips_abiflags;
- if (ph->p_filesz < sizeof (Elf_MIPS_ABIFlags_v0))
- REJECT (" %s: malformed PT_MIPS_ABIFLAGS found\n", l->l_name);
-
- mips_abiflags = (Elf_MIPS_ABIFlags_v0 *) (l->l_addr + ph->p_vaddr);
-
- if (__glibc_unlikely (mips_abiflags->flags2 != 0))
- REJECT (" %s: unknown MIPS.abiflags flags2: %u\n", l->l_name,
- mips_abiflags->flags2);
-
- l->l_mach.fpabi = mips_abiflags->fp_abi;
- l->l_mach.odd_spreg = (mips_abiflags->flags1
- & MIPS_AFL_FLAGS1_ODDSPREG) != 0;
- }
- else
- {
- l->l_mach.fpabi = -1;
- l->l_mach.odd_spreg = true;
- }
- }
- return false;
-}
-
/* Return a description of the specified floating-point ABI. */
static const char *
@@ -214,7 +169,7 @@ elf_machine_reject_phdr_p (const ElfW(Ph
{
struct abi_req existing_req;
- if (cached_fpabi_reject_phdr_p (l))
+ if (!__mips_abiflags_cache (l))
return true;
#if _MIPS_SIM == _ABIO32