From 83569fb894050db7430047da2219ca50c68f882a Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Tue, 31 Mar 2015 05:20:55 -0700 Subject: 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. --- elf/Makefile | 7 ++ elf/tst-protected1a.c | 236 +++++++++++++++++++++++++++++++++++++++++++++ elf/tst-protected1b.c | 242 +++++++++++++++++++++++++++++++++++++++++++++++ elf/tst-protected1mod.h | 41 ++++++++ elf/tst-protected1moda.c | 92 ++++++++++++++++++ elf/tst-protected1modb.c | 62 ++++++++++++ 6 files changed, 680 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 (limited to 'elf') diff --git a/elf/Makefile b/elf/Makefile index c8af5ba2c9..e852b5fcaa 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -213,6 +213,13 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ tst-initorder2d \ tst-relsort1mod1 tst-relsort1mod2 tst-array2dep \ tst-array5dep tst-null-argv-lib +ifeq (yes,$(have-protected-data)) +modules-names += tst-protected1moda tst-protected1modb +tests += tst-protected1a tst-protected1b +$(objpfx)tst-protected1a: $(addprefix $(objpfx),tst-protected1moda.so tst-protected1modb.so) +$(objpfx)tst-protected1b: $(addprefix $(objpfx),tst-protected1modb.so tst-protected1moda.so) +tst-protected1modb.so-no-z-defs = yes +endif ifeq (yesyes,$(have-fpie)$(build-shared)) modules-names += tst-piemod1 tests += tst-pie1 tst-pie2 diff --git a/elf/tst-protected1a.c b/elf/tst-protected1a.c new file mode 100644 index 0000000000..f4e76895a9 --- /dev/null +++ b/elf/tst-protected1a.c @@ -0,0 +1,236 @@ +/* Test the protected visibility when main is linked with moda and modb + in that order: + 1. Protected symbols, protected1, protected2 and protected3, defined + in moda, are used in moda. + 2. Protected symbol, protected3, defined in modb, are used in modb. + 3. Symbol, protected1, defined in moda, is also used in main and modb. + 4. Symbol, protected2, defined in main, is used in main. + 5. Symbol, protected3, defined in moda, is also 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 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; + } + + /* Check if we get the same address for the protected data symbol. */ + if (&protected3 != protected3a_p ()) + { + puts ("`protected3' in main and moda doesn't have same address"); + res = 1; + } + if (&protected3 == protected3b_p ()) + { + puts ("`protected3' in main and modb has same address"); + res = 1; + } + + /* Check if we get the right value for the protected data symbol. */ + if (protected3 != 5) + { + puts ("`protected3' in main and moda doesn't have same value"); + res = 1; + } + + /* Check `protected3' in moda. */ + if (!check_protected3a ()) + { + puts ("`protected3' in moda has the wrong value"); + res = 1; + } + + /* Check `protected3' in modb. */ + if (!check_protected3b ()) + { + puts ("`protected3' in modb 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; + } + + /* Set `protected3' in moda to 80. */ + set_protected3a (80); + + /* Check `protected3' in moda. */ + if (!check_protected3a ()) + { + puts ("`protected3' in moda has the wrong value"); + res = 1; + } + + /* Check if we get the updated value for the protected data symbol. */ + if (protected3 != 80) + { + puts ("`protected3' in main doesn't have the updated value"); + res = 1; + } + + /* Check `protected3' in modb. */ + if (!check_protected3b ()) + { + puts ("`protected3' in modb has the wrong value"); + res = 1; + } + + /* Set `protected3' in modb to 100. */ + set_protected3b (100); + + /* Check `protected3' in moda. */ + if (!check_protected3a ()) + { + puts ("`protected3' in moda has the wrong value"); + res = 1; + } + + /* Check if we get the updated value for the protected data symbol. */ + if (protected3 != 80) + { + puts ("`protected3' in main doesn't have the updated value"); + res = 1; + } + + /* Check `protected3' in modb. */ + if (!check_protected3b ()) + { + puts ("`protected3' in modb has the wrong value"); + res = 1; + } + + return res; +} diff --git a/elf/tst-protected1b.c b/elf/tst-protected1b.c new file mode 100644 index 0000000000..56352c406f --- /dev/null +++ b/elf/tst-protected1b.c @@ -0,0 +1,242 @@ +/* Test the protected visibility when main is linked with modb and moda + in that order: + 1. Protected symbols, protected1, protected2 and protected3, defined + in moda, are used in moda. + 2. Protected symbol, protected3, defined in modb, are used in modb + 3. Symbol, protected1, defined in modb, is used in main and modb. + 4. Symbol, protected2, defined in main, is used in main. + 5. Symbol, protected3, defined in modb, is also 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; + } + + /* Check if we get the same address for the protected data symbol. */ + if (&protected3 == protected3a_p ()) + { + puts ("`protected3' in main and moda has same address"); + res = 1; + } + if (&protected3 != protected3b_p ()) + { + puts ("`protected3' in main and modb doesn't have same address"); + res = 1; + } + + /* Check if we get the right value for the protected data symbol. */ + if (protected3 != -5) + { + puts ("`protected3' in main and modb doesn't have same value"); + res = 1; + } + + /* Check `protected3' in moda. */ + if (!check_protected3a ()) + { + puts ("`protected3' in moda has the wrong value"); + res = 1; + } + + /* Check `protected3' in modb. */ + if (!check_protected3b ()) + { + puts ("`protected3' in modb 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; + } + + /* 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; + } + + /* 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; + } + + /* Set `protected3' in moda to 80. */ + set_protected3a (80); + + /* Check `protected3' in moda. */ + if (!check_protected3a ()) + { + puts ("`protected3' in moda has the wrong value"); + res = 1; + } + + /* Check if we get the updated value for the protected data symbol. */ + if (protected3 != -5) + { + puts ("`protected3' in main doesn't have the updated value"); + res = 1; + } + + /* Check `protected3' in modb. */ + if (!check_protected3b ()) + { + puts ("`protected3' in modb has the wrong value"); + res = 1; + } + + /* Set `protected3' in modb to 100. */ + set_protected3b (100); + + /* Check `protected3' in moda. */ + if (!check_protected3a ()) + { + puts ("`protected3' in moda has the wrong value"); + res = 1; + } + + /* Check if we get the updated value for the protected data symbol. */ + if (protected3 != 100) + { + puts ("`protected3' in main doesn't have the updated value"); + res = 1; + } + + /* Check `protected3' in modb. */ + if (!check_protected3b ()) + { + puts ("`protected3' in modb has the wrong value"); + res = 1; + } + + return res; +} diff --git a/elf/tst-protected1mod.h b/elf/tst-protected1mod.h new file mode 100644 index 0000000000..301e019dd8 --- /dev/null +++ b/elf/tst-protected1mod.h @@ -0,0 +1,41 @@ +/* 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 int protected3; + +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); + +extern void set_expected_protected3a (int); +extern void set_protected3a (int); +extern int check_protected3a (void); +extern int *protected3a_p (void); +extern void set_expected_protected3b (int); +extern void set_protected3b (int); +extern int check_protected3b (void); +extern int *protected3b_p (void); diff --git a/elf/tst-protected1moda.c b/elf/tst-protected1moda.c new file mode 100644 index 0000000000..720f474281 --- /dev/null +++ b/elf/tst-protected1moda.c @@ -0,0 +1,92 @@ +/* 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; +int protected3 = 5; +static int expected_protected3 = 5; + +asm (".protected protected1"); +asm (".protected protected2"); +asm (".protected protected3"); + +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; +} + +void +set_expected_protected3a (int i) +{ + expected_protected3 = i; +} + +void +set_protected3a (int i) +{ + protected3 = i; + set_expected_protected3a (i); +} + +int +check_protected3a (void) +{ + return protected3 == expected_protected3; +} + +int * +protected3a_p (void) +{ + return &protected3; +} diff --git a/elf/tst-protected1modb.c b/elf/tst-protected1modb.c new file mode 100644 index 0000000000..ddfa646ec3 --- /dev/null +++ b/elf/tst-protected1modb.c @@ -0,0 +1,62 @@ +/* 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; +int protected3 = -5; +static int expected_protected3 = -5; + +asm (".protected protected3"); + +void +set_protected1b (int i) +{ + protected1 = i; +} + +int * +protected1b_p (void) +{ + return &protected1; +} + +void +set_expected_protected3b (int i) +{ + expected_protected3 = i; +} + +void +set_protected3b (int i) +{ + protected3 = i; + set_expected_protected3b (i); +} + +int +check_protected3b (void) +{ + return protected3 == expected_protected3; +} + +int * +protected3b_p (void) +{ + return &protected3; +} -- cgit 1.4.1