glibc/sysdeps/aarch64/tst-ifunc-arg-2.c
Szabolcs Nagy 2b8a3c86e7 aarch64: new ifunc resolver ABI
Passing a second argument to the ifunc resolver allows accessing
AT_HWCAP2 values from the resolver. AArch64 will start using AT_HWCAP2
on linux because for ilp32 to remain compatible with lp64 ABI no more
than 32bit hwcap flags can be in AT_HWCAP which is already used up.

Currently the relocation ordering logic does not guarantee that ifunc
resolvers can call libc apis or access libc objects, so only the
resolver arguments and runtime environment dependent instructions can
be used to do the dispatch (this affects ifunc resolvers outside of
the libc).

Since ifunc resolver is target specific and only supposed to be
called by the dynamic linker, the call ABI can be changed in a
backward compatible way:

Old call ABI passed hwcap as uint64_t, new abi sets the
_IFUNC_ARG_HWCAP flag in the hwcap and passes a second argument
that's a pointer to an extendible struct. A resolver has to check
the _IFUNC_ARG_HWCAP flag before accessing the second argument.

The new sys/ifunc.h installed header has the definitions for the
new ABI, everything is in the implementation reserved namespace.

An alternative approach is to try to support extern calls from ifunc
resolvers such as getauxval, but that seems non-trivial
https://sourceware.org/ml/libc-alpha/2017-01/msg00468.html

	* sysdeps/aarch64/Makefile: Install sys/ifunc.h and add tests.
	* sysdeps/aarch64/dl-irel.h (elf_ifunc_invoke): Update to new ABI.
	* sysdeps/aarch64/sys/ifunc.h: New file.
	* sysdeps/aarch64/tst-ifunc-arg-1.c: New file.
	* sysdeps/aarch64/tst-ifunc-arg-2.c: New file.
2019-07-04 11:13:32 +01:00

67 lines
1.8 KiB
C

/* Test R_*_IRELATIVE resolver with second argument.
Copyright (C) 2019 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 <stdint.h>
#include <sys/auxv.h>
#include <sys/ifunc.h>
#include <support/check.h>
static int
one (void)
{
return 1;
}
static uint64_t saved_arg1;
static __ifunc_arg_t saved_arg2;
/* local ifunc symbol. */
int
__attribute__ ((visibility ("hidden")))
foo (void);
static void *
__attribute__ ((used))
foo_ifunc (uint64_t, const __ifunc_arg_t *) __asm__ ("foo");
__asm__(".type foo, %gnu_indirect_function");
static void *
__attribute__ ((used))
inhibit_stack_protector
foo_ifunc (uint64_t arg1, const __ifunc_arg_t *arg2)
{
saved_arg1 = arg1;
if (arg1 & _IFUNC_ARG_HWCAP)
saved_arg2 = *arg2;
return (void *) one;
}
static int
do_test (void)
{
TEST_VERIFY (foo () == 1);
TEST_VERIFY (saved_arg1 & _IFUNC_ARG_HWCAP);
TEST_COMPARE ((uint32_t)saved_arg1, (uint32_t)getauxval (AT_HWCAP));
TEST_COMPARE (saved_arg2._size, sizeof (__ifunc_arg_t));
TEST_COMPARE (saved_arg2._hwcap, getauxval (AT_HWCAP));
TEST_COMPARE (saved_arg2._hwcap2, getauxval (AT_HWCAP2));
return 0;
}
#include <support/test-driver.c>