From patchwork Fri Mar 6 19:40:59 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 5499 Received: (qmail 11363 invoked by alias); 6 Mar 2015 19:41:07 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 11350 invoked by uid 89); 6 Mar 2015 19:41:06 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=4.1 required=5.0 tests=AWL, BAYES_50, FREEMAIL_FROM, KAM_FROM_URIBL_PCCC, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=no version=3.3.2 X-HELO: mail-ob0-f174.google.com MIME-Version: 1.0 X-Received: by 10.60.74.41 with SMTP id q9mr12449638oev.61.1425670861283; Fri, 06 Mar 2015 11:41:01 -0800 (PST) In-Reply-To: References: <20150306002424.GA17971@intel.com> Date: Fri, 6 Mar 2015 11:40:59 -0800 Message-ID: Subject: Re: [PATCH 2/2] Add a testcase for copy reloc against protected data From: "H.J. Lu" To: Joseph Myers Cc: GNU C Library On Fri, Mar 6, 2015 at 11:09 AM, Joseph Myers wrote: > On Thu, 5 Mar 2015, H.J. Lu wrote: > >> if test $libc_cv_visibility_attribute = yes; then >> + AC_CACHE_CHECK(linker support for protected data symbol, >> + libc_cv_protected_data, >> + [cat > conftest.c <> + int bar __attribute__ ((visibility ("protected"))) = 1; >> +EOF >> + libc_cv_protected_data=no >> + if AC_TRY_COMMAND(${CC-cc} -fPIC -shared conftest.c -o conftest.so); then > > Use -nostdlib -nostartfiles on all configure tests involving linking so > that they work correctly in bootstrap configurations, unless there is a > clear reason they cannot work with -nostdlib -nostartfiles (in which case > there should be thorough comments about the issue). > >> + cat > conftest.c <> + extern int bar; >> + int main (void) { return bar; } >> +EOF >> + if AC_TRY_COMMAND(${CC-cc} conftest.c -o conftest conftest.so); then > > Likewise; you may need to use -static as well (or LIBC_TRY_LINK_STATIC). > Done. Here is an updated patch. > Suppose I configure / build with new binutils but a GCC version without > your patches. What will the results be? That the tests don't build / > run? That they build / run but fail (best avoided if possible)? In > either case, you need clear documentation for architecture maintainers on > what GCC versions (*not* requiring any uncommitted GCC patches) must be > used to identify whether architecture-specific changes are needed and to > test such changes. > I will submit a separate patch to address GCC issue. From ab16864ad041c68a3ae514fc1e9b62e69a037ea2 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Thu, 5 Mar 2015 11:36:35 -0800 Subject: [PATCH 2/3] Add a testcase for copy reloc against protected data Linkers in some versions of binutils 2.25 and 2.26 don't support protected data symbol with error messsage like: /usr/bin/ld: copy reloc against protected `bar' is invalid /usr/bin/ld: failed to set dynamic section sizes: Bad value We check if linker supports copy reloc against protected data symbol to avoid running the test if linker is broken. [BZ #17711] * config.make.in (have-protected-data): New. * configure.ac: Check linker support for protected data symbol. * configure: Regenerated. * elf/Makefile (modules-names): Add tst-protected1moda and tst-protected1modb if $(have-protected-data) is yes. (tests): Add tst-protected1a and tst-protected1b if $(have-protected-data) is yes. ($(objpfx)tst-protected1a): New. ($(objpfx)tst-protected1b): Likewise. (tst-protected1modb.so-no-z-defs): Likewise. * elf/tst-protected1a.c: New file. * elf/tst-protected1b.c: Likewise. * elf/tst-protected1mod.h: Likewise. * elf/tst-protected1moda.c: Likewise. * elf/tst-protected1modb.c: Likewise. --- config.make.in | 1 + configure | 40 +++++++++++++ configure.ac | 23 +++++++ elf/Makefile | 7 +++ elf/tst-protected1a.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++ elf/tst-protected1b.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++ elf/tst-protected1mod.h | 31 ++++++++++ elf/tst-protected1moda.c | 64 ++++++++++++++++++++ elf/tst-protected1modb.c | 33 ++++++++++ 9 files changed, 504 insertions(+) create mode 100644 elf/tst-protected1a.c create mode 100644 elf/tst-protected1b.c create mode 100644 elf/tst-protected1mod.h create mode 100644 elf/tst-protected1moda.c create mode 100644 elf/tst-protected1modb.c diff --git a/config.make.in b/config.make.in index ad4dd30..5a18dae 100644 --- a/config.make.in +++ b/config.make.in @@ -50,6 +50,7 @@ enable-werror = @enable_werror@ have-z-combreloc = @libc_cv_z_combreloc@ have-z-execstack = @libc_cv_z_execstack@ have-Bgroup = @libc_cv_Bgroup@ +have-protected-data = @libc_cv_protected_data@ with-fp = @with_fp@ old-glibc-headers = @old_glibc_headers@ unwind-find-fde = @libc_cv_gcc_unwind_find_fde@ diff --git a/configure b/configure index 71cc6bb..79864b7 100755 --- a/configure +++ b/configure @@ -634,6 +634,7 @@ libc_cv_z_combreloc ASFLAGS_config libc_cv_Bgroup libc_cv_cc_with_libunwind +libc_cv_protected_data BISON INSTALL_INFO PERL @@ -5734,6 +5735,45 @@ $as_echo "$libc_cv_visibility_attribute" >&6; } fi if test $libc_cv_visibility_attribute = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker support for protected data symbol" >&5 +$as_echo_n "checking linker support for protected data symbol... " >&6; } +if ${libc_cv_protected_data+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.c <&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cat > conftest.c <&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + libc_cv_protected_data=yes + fi + fi + rm -f conftest.* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_protected_data" >&5 +$as_echo "$libc_cv_protected_data" >&6; } +else + libc_cv_protected_data=no +fi + + +if test $libc_cv_visibility_attribute = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for broken __attribute__((visibility()))" >&5 $as_echo_n "checking for broken __attribute__((visibility()))... " >&6; } if ${libc_cv_broken_visibility_attribute+:} false; then : diff --git a/configure.ac b/configure.ac index 678c739..39f3e86 100644 --- a/configure.ac +++ b/configure.ac @@ -1220,6 +1220,29 @@ EOF fi if test $libc_cv_visibility_attribute = yes; then + AC_CACHE_CHECK(linker support for protected data symbol, + libc_cv_protected_data, + [cat > conftest.c < conftest.c < conftest.c <. */ + +/* This file must be compiled as PIE to avoid copy relocation when + accessing protected symbols defined in shared libaries since copy + relocation doesn't work with protected symbols and linker in + binutils 2.26 enforces this rule. */ + +#include +#include +#include + +#include "tst-protected1mod.h" + +/* Prototype for our test function. */ +extern int do_test (void); + +int protected2 = -1; + +#define TEST_FUNCTION do_test () + +/* This defines the `main' function and some more. */ +#include + +int +do_test (void) +{ + int res = 0; + + /* Check if we get the same address for the protected data symbol. */ + if (&protected1 != protected1a_p ()) + { + puts ("`protected1' in main and moda doesn't have same address"); + res = 1; + } + if (&protected1 != protected1b_p ()) + { + puts ("`protected1' in main and modb doesn't have same address"); + res = 1; + } + + /* Check if we get the right value for the protected data symbol. */ + if (protected1 != 3) + { + puts ("`protected1' in main and moda doesn't have same value"); + res = 1; + } + + /* Check if we get the right value for data defined in executable. */ + if (protected2 != -1) + { + puts ("`protected2' in main has the wrong value"); + res = 1; + } + + /* Check `protected1' in moda. */ + if (!check_protected1 ()) + { + puts ("`protected1' in moda has the wrong value"); + res = 1; + } + + /* Check `protected2' in moda. */ + if (!check_protected2 ()) + { + puts ("`protected2' in moda has the wrong value"); + res = 1; + } + + /* Set `protected2' in moda to 30. */ + set_protected2 (300); + + /* Check `protected2' in moda. */ + if (!check_protected2 ()) + { + puts ("`protected2' in moda has the wrong value"); + res = 1; + } + + /* Set `protected1' in moda to 30. */ + set_protected1a (30); + + /* Check `protected1' in moda. */ + if (!check_protected1 ()) + { + puts ("`protected1' in moda has the wrong value"); + res = 1; + } + + /* Check if we get the updated value for the protected data symbol. */ + if (protected1 != 30) + { + puts ("`protected1' in main doesn't have the updated value"); + res = 1; + } + + protected2 = -300; + + /* Check `protected2' in moda. */ + if (!check_protected2 ()) + { + puts ("`protected2' in moda has the wrong value"); + res = 1; + } + + /* Check if data defined in executable is changed. */ + if (protected2 != -300) + { + puts ("`protected2' in main is changed"); + res = 1; + } + + /* Set `protected1' in modb to 40. */ + set_protected1b (40); + set_expected_protected1 (40); + + /* Check `protected1' in moda. */ + if (!check_protected1 ()) + { + puts ("`protected1' in moda has the wrong value"); + res = 1; + } + + /* Check if we get the updated value for the protected data symbol. */ + if (protected1 != 40) + { + puts ("`protected1' in main doesn't have the updated value"); + res = 1; + } + + return res; +} diff --git a/elf/tst-protected1b.c b/elf/tst-protected1b.c new file mode 100644 index 0000000..afc34f1 --- /dev/null +++ b/elf/tst-protected1b.c @@ -0,0 +1,152 @@ +/* Test the protected visibility when main is linked with modb and moda + in that order: + 1. Protected symbols, protected1 and protected2, defined in moda, are + used in moda. + 2. Symbol, protected1, defined in modb, is used in main and modb. + 3. Symbol, protected2, defined in main, is used in main. + + 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 + . */ + +/* This file must be compiled as PIE to avoid copy relocation when + accessing protected symbols defined in shared libaries since copy + relocation doesn't work with protected symbols and linker in + binutils 2.26 enforces this rule. */ + +#include +#include +#include + +#include "tst-protected1mod.h" + +/* Prototype for our test function. */ +extern int do_test (void); + +int protected2 = -1; + +#define TEST_FUNCTION do_test () + +/* This defines the `main' function and some more. */ +#include + +int +do_test (void) +{ + int res = 0; + + /* Check if we get the same address for the protected data symbol. */ + if (&protected1 == protected1a_p ()) + { + puts ("`protected1' in main and moda has same address"); + res = 1; + } + if (&protected1 != protected1b_p ()) + { + puts ("`protected1' in main and modb doesn't have same address"); + res = 1; + } + + /* Check if we get the right value for the protected data symbol. */ + if (protected1 != -3) + { + puts ("`protected1' in main and modb doesn't have same value"); + res = 1; + } + + /* Check if we get the right value for data defined in executable. */ + if (protected2 != -1) + { + puts ("`protected2' in main has the wrong value"); + res = 1; + } + + /* Check `protected1' in moda. */ + if (!check_protected1 ()) + { + puts ("`protected1' in moda has the wrong value"); + res = 1; + } + + /* Check `protected2' in moda. */ + if (!check_protected2 ()) + { + puts ("`protected2' in moda has the wrong value"); + res = 1; + } + + /* Set `protected2' in moda to 30. */ + set_protected2 (300); + + /* Check `protected2' in moda. */ + if (!check_protected2 ()) + { + puts ("`protected2' in moda has the wrong value"); + res = 1; + } + + /* Set `protected1' in moda to 30. */ + set_protected1a (30); + + /* Check `protected1' in moda. */ + if (!check_protected1 ()) + { + puts ("`protected1' in moda has the wrong value"); + res = 1; + } + + /* Check if we get the same value for the protected data symbol. */ + if (protected1 != -3) + { + puts ("`protected1' in main has the wrong value"); + res = 1; + } + + protected2 = -300; + + /* Check `protected2' in moda. */ + if (!check_protected2 ()) + { + puts ("`protected2' in moda has the wrong value"); + res = 1; + } + + /* Check if data defined in executable is changed. */ + if (protected2 != -300) + { + puts ("`protected2' in main is changed"); + res = 1; + } + + /* Set `protected1' in modb to 40. */ + set_protected1b (40); + + /* Check `protected1' in moda. */ + if (!check_protected1 ()) + { + puts ("`protected1' in moda has the wrong value"); + res = 1; + } + + /* Check if we get the updated value for the protected data symbol. */ + if (protected1 != 40) + { + puts ("`protected1' in main doesn't have the updated value"); + res = 1; + } + + return res; +} diff --git a/elf/tst-protected1mod.h b/elf/tst-protected1mod.h new file mode 100644 index 0000000..818208a --- /dev/null +++ b/elf/tst-protected1mod.h @@ -0,0 +1,31 @@ +/* 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 + . */ + +/* Prototypes for the functions in the DSOs. */ +extern int protected1; +extern int protected2; + +extern void set_protected1a (int); +extern void set_protected1b (int); +extern int *protected1a_p (void); +extern int *protected1b_p (void); + +extern void set_expected_protected1 (int); +extern int check_protected1 (void); + +extern void set_protected2 (int); +extern int check_protected2 (void); diff --git a/elf/tst-protected1moda.c b/elf/tst-protected1moda.c new file mode 100644 index 0000000..1ae9e32 --- /dev/null +++ b/elf/tst-protected1moda.c @@ -0,0 +1,64 @@ +/* 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 + . */ + +#include "tst-protected1mod.h" + +int protected1 = 3; +static int expected_protected1 = 3; +int protected2 = 4; +static int expected_protected2 = 4; + +asm (".protected protected1"); +asm (".protected protected2"); + +void +set_protected1a (int i) +{ + protected1 = i; + set_expected_protected1 (i); +} + +void +set_expected_protected1 (int i) +{ + expected_protected1 = i; +} + +int * +protected1a_p (void) +{ + return &protected1; +} + +int +check_protected1 (void) +{ + return protected1 == expected_protected1; +} + +void +set_protected2 (int i) +{ + protected2 = i; + expected_protected2 = i; +} + +int +check_protected2 (void) +{ + return protected2 == expected_protected2; +} diff --git a/elf/tst-protected1modb.c b/elf/tst-protected1modb.c new file mode 100644 index 0000000..e98bbac --- /dev/null +++ b/elf/tst-protected1modb.c @@ -0,0 +1,33 @@ +/* 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 + . */ + +#include +#include "tst-protected1mod.h" + +int protected1 = -3; + +void +set_protected1b (int i) +{ + protected1 = i; +} + +int * +protected1b_p (void) +{ + return &protected1; +} -- 1.9.3