diff --git a/ChangeLog b/ChangeLog index ed05044fe8..705dc7d6d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2019-02-28 Florian Weimer + + [BZ #23937] + elf: Add test with a local IFUNC resolver. + * elf/ifuncmain9.c: New file. + * elf/ifuncmain9pic.c: Likewise. + * elf/ifuncmain9picstatic.c: Likewise. + * elf/ifuncmain9pie.c: Likewise. + * elf/ifuncmain9static.c: Likewise. + * elf/Makefile [multi-arch] (tests-ifuncstatic): Add + ifuncmain9static, ifuncmain9picstatic. + * elf/Makefile [multi-arch && build-shared] (tests-internal): + Add ifuncmain9, ifuncmain9pic. + * elf/Makefile [multi-arch && build-shared && have-fpie] + (ifunc-pie-tests): Add ifuncmain9pie. + (CFLAGS-ifuncmain9pic.c): Add $(pic-ccflag). + (CFLAGS-ifuncmain9picstatic.c): Likewise. + (CFLAGS-ifuncmain9pie.c): Add $(pie-ccflag). + 2019-02-27 H.J. Lu * configure.ac (have-ifunc): New LIBC_CONFIG_VAR. diff --git a/elf/Makefile b/elf/Makefile index e44960e5fe..55204073a3 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -326,23 +326,26 @@ tests-ifuncstatic := ifuncmain1static ifuncmain1picstatic \ ifuncmain2static ifuncmain2picstatic \ ifuncmain4static ifuncmain4picstatic \ ifuncmain5static ifuncmain5picstatic \ - ifuncmain7static ifuncmain7picstatic + ifuncmain7static ifuncmain7picstatic \ + ifuncmain9static ifuncmain9picstatic tests-static += $(tests-ifuncstatic) tests-internal += $(tests-ifuncstatic) ifeq (yes,$(build-shared)) +# Note: sysdeps/x86_64/ifuncmain8.c uses ifuncmain8. tests-internal += \ ifuncmain1 ifuncmain1pic ifuncmain1vis ifuncmain1vispic \ ifuncmain1staticpic \ ifuncmain2 ifuncmain2pic ifuncmain3 ifuncmain4 \ ifuncmain5 ifuncmain5pic ifuncmain5staticpic \ - ifuncmain7 ifuncmain7pic + ifuncmain7 ifuncmain7pic \ + ifuncmain9 ifuncmain9pic ifunc-test-modules = ifuncdep1 ifuncdep1pic ifuncdep2 ifuncdep2pic \ ifuncdep5 ifuncdep5pic extra-test-objs += $(ifunc-test-modules:=.o) test-internal-extras += $(ifunc-test-modules) ifeq (yes,$(have-fpie)) ifunc-pie-tests = ifuncmain1pie ifuncmain1vispie ifuncmain1staticpie \ - ifuncmain5pie ifuncmain6pie ifuncmain7pie + ifuncmain5pie ifuncmain6pie ifuncmain7pie ifuncmain9pie ifeq (yes,$(have-textrel_ifunc)) ifunc-pie-tests += tst-ifunc-textrel endif @@ -1276,6 +1279,8 @@ CFLAGS-ifuncmain5staticpic.c += $(pic-ccflag) CFLAGS-ifuncdep5pic.c += $(pic-ccflag) CFLAGS-ifuncmain7pic.c += $(pic-ccflag) CFLAGS-ifuncmain7picstatic.c += $(pic-ccflag) +CFLAGS-ifuncmain9pic.c += $(pic-ccflag) +CFLAGS-ifuncmain9picstatic.c += $(pic-ccflag) LDFLAGS-ifuncmain3 = -Wl,-export-dynamic @@ -1285,6 +1290,7 @@ CFLAGS-ifuncmain1staticpie.c += $(pie-ccflag) CFLAGS-ifuncmain5pie.c += $(pie-ccflag) CFLAGS-ifuncmain6pie.c += $(pie-ccflag) CFLAGS-ifuncmain7pie.c += $(pie-ccflag) +CFLAGS-ifuncmain9pie.c += $(pie-ccflag) CFLAGS-tst-ifunc-textrel.c += $(pic-ccflag) $(objpfx)ifuncmain1pie: $(objpfx)ifuncmod1.so diff --git a/elf/ifuncmain9.c b/elf/ifuncmain9.c new file mode 100644 index 0000000000..a8a9c49dd1 --- /dev/null +++ b/elf/ifuncmain9.c @@ -0,0 +1,107 @@ +/* Test for IFUNC handling with local definitions. + 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 + . */ + +/* This test is based on gcc.dg/attr-ifunc-4.c. */ + +#include + +#ifdef HAVE_GCC_IFUNC + +# include +# include + +/* Do not use the test framework, so that the process setup is not + disturbed. */ + +static volatile int implementation_called; +static volatile int resolver_called; + +/* Just a random constant, to check that we called the right + function. */ +enum { random_constant = 0x3a88d66d }; + +static int +implementation (void) +{ + ++implementation_called; + return random_constant; +} + +static __typeof__ (implementation) * +resolver (void) +{ + ++resolver_called; + return implementation; +} + +static int magic (void) __attribute__ ((ifunc ("resolver"))); + +int +main (void) +{ + bool errors = false; + + if (implementation_called != 0) + { + printf ("error: initial value of implementation_called is not zero:" + " %d\n", implementation_called); + errors = true; + } + + /* This can be zero if the reference is bound lazily. */ + printf ("info: initial value of resolver_called: %d\n", resolver_called); + + int magic_value = magic (); + if (magic_value != random_constant) + { + printf ("error: invalid magic value: 0x%x\n", magic_value); + errors = true; + } + + printf ("info: resolver_called value: %d\n", resolver_called); + if (resolver_called == 0) + { + /* In theory, the resolver could be called multiple times if + several relocations are needed. */ + puts ("error: invalid resolver_called value (must not be zero)"); + errors = true; + } + + printf ("info: implementation_called value: %d\n", implementation_called); + if (implementation_called != 1) + { + puts ("error: invalid implementation_called value (must be 1)"); + errors = true; + } + + return errors; +} + +#else /* !HAVE_GCC_IFUNC */ + +# include + +static int +do_test (void) +{ + FAIL_UNSUPPORTED ("GCC does not support the ifunc attribute"); + return 1; /* Not reachable. */ +} + +# include +#endif diff --git a/elf/ifuncmain9pic.c b/elf/ifuncmain9pic.c new file mode 100644 index 0000000000..6151a45e88 --- /dev/null +++ b/elf/ifuncmain9pic.c @@ -0,0 +1 @@ +#include "ifuncmain9.c" diff --git a/elf/ifuncmain9picstatic.c b/elf/ifuncmain9picstatic.c new file mode 100644 index 0000000000..6151a45e88 --- /dev/null +++ b/elf/ifuncmain9picstatic.c @@ -0,0 +1 @@ +#include "ifuncmain9.c" diff --git a/elf/ifuncmain9pie.c b/elf/ifuncmain9pie.c new file mode 100644 index 0000000000..6151a45e88 --- /dev/null +++ b/elf/ifuncmain9pie.c @@ -0,0 +1 @@ +#include "ifuncmain9.c" diff --git a/elf/ifuncmain9static.c b/elf/ifuncmain9static.c new file mode 100644 index 0000000000..6151a45e88 --- /dev/null +++ b/elf/ifuncmain9static.c @@ -0,0 +1 @@ +#include "ifuncmain9.c"