[PATCH 3/3] Update tests for protected data and function symbols
H.J. Lu
hjl.tools@gmail.com
Thu Oct 7 20:08:13 GMT 2021
Protected data and function symbols don't work well without
-fno-direct-extern-access:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37611
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=44166
1. Compile tst-protected1[ab].c and tst-protected1mod[ab].c with
-fno-direct-extern-access if possible so that GOT entries are used
for undefined data accesses.
2. Add tests for protected function pointers.
3. Build tst-prelink.c with direct external access to keep COPY
relocation.
---
elf/Makefile | 54 ++++++++++++++++
elf/tst-protected1moda.c | 10 +--
elf/tst-protected1modb.c | 4 +-
elf/tst-protected2a.c | 130 ++++++++++++++++++++++++++++++++++++++
elf/tst-protected2apie.c | 1 +
elf/tst-protected2b.c | 121 +++++++++++++++++++++++++++++++++++
elf/tst-protected2bpie.c | 1 +
elf/tst-protected2mod.h | 35 ++++++++++
elf/tst-protected2moda.c | 52 +++++++++++++++
elf/tst-protected2moda2.c | 41 ++++++++++++
elf/tst-protected2modb.c | 45 +++++++++++++
elf/tst-protected2modb2.c | 28 ++++++++
12 files changed, 512 insertions(+), 10 deletions(-)
create mode 100644 elf/tst-protected2a.c
create mode 100644 elf/tst-protected2apie.c
create mode 100644 elf/tst-protected2b.c
create mode 100644 elf/tst-protected2bpie.c
create mode 100644 elf/tst-protected2mod.h
create mode 100644 elf/tst-protected2moda.c
create mode 100644 elf/tst-protected2moda2.c
create mode 100644 elf/tst-protected2modb.c
create mode 100644 elf/tst-protected2modb2.c
diff --git a/elf/Makefile b/elf/Makefile
index 26986c0692..85cfb876b5 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -380,15 +380,59 @@ 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
+ifeq (yes,$(have-fno-direct-extern-access))
+CFLAGS-tst-protected1a.c += -fno-direct-extern-access
+CFLAGS-tst-protected1b.c += -fno-direct-extern-access
+CFLAGS-tst-protected1moda.c += -fno-direct-extern-access
+CFLAGS-tst-protected1modb.c += -fno-direct-extern-access
+else
# These tests fail with GCC versions prior to 5.1 and with some versions
# of binutils. See https://sourceware.org/bugzilla/show_bug.cgi?id=17709
# and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65248 for details.
# Perhaps in future we can make these XFAILs conditional on some detection
# of compiler/linker behavior/version.
+# NB: These tests pass with -fno-direct-extern-access when GOT entries
+# are used for undefined data accesses.
test-xfail-tst-protected1a = yes
test-xfail-tst-protected1b = yes
endif
+ifeq (yes,$(have-z-indirect-extern-access))
+LDFLAGS-tst-protected1moda.so += -Wl,-z,indirect-extern-access
+LDFLAGS-tst-protected1modb.so += -Wl,-z,indirect-extern-access
+endif
+endif
ifeq (yesyes,$(have-fpie)$(build-shared))
+ifeq (yes,$(have-z-indirect-extern-access))
+modules-names += tst-protected2moda tst-protected2modb
+tests += tst-protected2a tst-protected2b
+tests += tst-protected2apie tst-protected2bpie
+tests-pie += tst-protected2apie tst-protected2bpie
+test-extras += tst-protected2moda2 tst-protected2modb2
+extra-test-objs += tst-protected2moda2.os tst-protected2modb2.os
+LDFLAGS-tst-protected2moda.so += -Wl,-z,indirect-extern-access
+LDFLAGS-tst-protected2modb.so += -Wl,-z,indirect-extern-access
+CFLAGS-tst-protected2apie.c += $(PIE-ccflag)
+CFLAGS-tst-protected2bpie.c += $(PIE-ccflag)
+ifeq (yes,$(have-fno-direct-extern-access))
+CFLAGS-tst-protected2a.c += -fno-direct-extern-access
+CFLAGS-tst-protected2b.c += -fno-direct-extern-access
+CFLAGS-tst-protected2moda.c += -fno-direct-extern-access
+CFLAGS-tst-protected2moda2.c += -fno-direct-extern-access
+CFLAGS-tst-protected2modb.c += -fno-direct-extern-access
+CFLAGS-tst-protected2modb2.c += -fno-direct-extern-access
+else
+# These non-PIE tests fail when GOT entries are not used for undefined
+# function pointers.
+test-xfail-tst-protected2a = yes
+test-xfail-tst-protected2b = yes
+endif
+$(objpfx)tst-protected2moda.so: $(objpfx)tst-protected2moda2.os
+$(objpfx)tst-protected2modb.so: $(objpfx)tst-protected2modb2.os
+$(objpfx)tst-protected2a: $(addprefix $(objpfx),tst-protected2moda.so tst-protected2modb.so)
+$(objpfx)tst-protected2b: $(addprefix $(objpfx),tst-protected2modb.so tst-protected2moda.so)
+$(objpfx)tst-protected2apie: $(addprefix $(objpfx),tst-protected2moda.so tst-protected2modb.so)
+$(objpfx)tst-protected2bpie: $(addprefix $(objpfx),tst-protected2modb.so tst-protected2moda.so)
+endif
modules-names += tst-piemod1
tests += tst-pie1 tst-pie2 tst-dlopen-pie tst-dlopen-tlsmodid-pie \
tst-dlopen-self-pie
@@ -483,6 +527,16 @@ tests += tst-prelink
tests-internal += tst-prelink-cmp
# Don't compile tst-prelink.c with PIE for GLOB_DAT relocation.
CFLAGS-tst-prelink.c += -fno-pie
+ifeq ($(have-fno-direct-extern-access),yes)
+# Compile tst-prelink.c with -fdirect-extern-acces to keepp COPY
+# relocation.
+CFLAGS-tst-prelink.c += -fdirect-extern-access
+endif
+ifeq ($(have-z-indirect-extern-access),yes)
+# Link tst-prelink with -z noindirect-extern-access to keepp COPY
+# relocation.
+LDFLAGS-tst-prelink += -Wl,-z,noindirect-extern-access
+endif
tst-prelink-no-pie = yes
endif
diff --git a/elf/tst-protected1moda.c b/elf/tst-protected1moda.c
index eeb18306bb..3d0eb1e877 100644
--- a/elf/tst-protected1moda.c
+++ b/elf/tst-protected1moda.c
@@ -17,17 +17,13 @@
#include "tst-protected1mod.h"
-int protected1 = 3;
+int protected1 __attribute__ ((visibility("protected"))) = 3;
static int expected_protected1 = 3;
-int protected2 = 4;
+int protected2 __attribute__ ((visibility("protected"))) = 4;
static int expected_protected2 = 4;
-int protected3 = 5;
+int protected3 __attribute__ ((visibility("protected"))) = 5;
static int expected_protected3 = 5;
-asm (".protected protected1");
-asm (".protected protected2");
-asm (".protected protected3");
-
void
set_protected1a (int i)
{
diff --git a/elf/tst-protected1modb.c b/elf/tst-protected1modb.c
index 2cb1e61b17..ca82c64689 100644
--- a/elf/tst-protected1modb.c
+++ b/elf/tst-protected1modb.c
@@ -19,11 +19,9 @@
#include "tst-protected1mod.h"
int protected1 = -3;
-int protected3 = -5;
+int protected3 __attribute__ ((visibility("protected"))) = -5;
static int expected_protected3 = -5;
-asm (".protected protected3");
-
void
set_protected1b (int i)
{
diff --git a/elf/tst-protected2a.c b/elf/tst-protected2a.c
new file mode 100644
index 0000000000..21b666e12b
--- /dev/null
+++ b/elf/tst-protected2a.c
@@ -0,0 +1,130 @@
+/* Test the protected visibility when main is linked with moda and modb
+ in that order:
+ 1. Protected function symbols, protected1, protected2 and protected3,
+ defined in moda, are used in moda.
+ 2. Protected function 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) 2021 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tst-protected2mod.h"
+
+int
+protected2 (void)
+{
+ return -1;
+}
+
+int
+__attribute__ ((weak, noclone, noinline))
+call_ptr (protected_func_type ptr)
+{
+ return ptr ();
+}
+
+int
+do_test (void)
+{
+ int res = 0;
+
+ /* Check if we get the same address for the protected function symbol. */
+ protected_func_type ptr = protected1a_p ();
+ if (&protected1 != ptr)
+ {
+ puts ("`protected1' in main and moda doesn't have the same address");
+ res = 1;
+ }
+ ptr = protected1b_p ();
+ if (&protected1 != ptr)
+ {
+ puts ("`protected1' in main and modb doesn't have the same address");
+ res = 1;
+ }
+
+ /* Check if we get the right protected function symbol. */
+ if (call_ptr (ptr) != 3)
+ {
+ puts ("`protected1' in main and moda doesn't return the same value");
+ res = 1;
+ }
+
+ /* Check if we get the right function defined in executable. */
+ if (protected2 () != -1)
+ {
+ puts ("`protected2' in main returns the wrong value");
+ res = 1;
+ }
+
+ /* Check `protected1' in moda. */
+ if (!check_protected1 ())
+ {
+ puts ("`protected1' in moda returns the wrong value");
+ res = 1;
+ }
+
+ /* Check `protected2' in moda. */
+ if (!check_protected2 ())
+ {
+ puts ("`protected2' in moda returns the wrong value");
+ res = 1;
+ }
+
+ /* Check if we get the same address for the protected function symbol. */
+ if (&protected3 != protected3a_p ())
+ {
+ puts ("`protected3' in main and moda doesn't have the same address");
+ res = 1;
+ }
+ if (&protected3 == protected3b_p ())
+ {
+ puts ("`protected3' in main and modb has the 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 return the 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;
+ }
+
+ return res;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-protected2apie.c b/elf/tst-protected2apie.c
new file mode 100644
index 0000000000..28a7aa3d1a
--- /dev/null
+++ b/elf/tst-protected2apie.c
@@ -0,0 +1 @@
+#include "tst-protected2a.c"
diff --git a/elf/tst-protected2b.c b/elf/tst-protected2b.c
new file mode 100644
index 0000000000..500323e33f
--- /dev/null
+++ b/elf/tst-protected2b.c
@@ -0,0 +1,121 @@
+/* Test the protected visibility when main is linked with modb and moda
+ in that order:
+ 1. Protected function symbols, protected1, protected2 and protected3,
+ defined in moda, are used in moda.
+ 2. Protected function 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) 2021 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tst-protected2mod.h"
+
+int
+protected2 (void)
+{
+ return -1;
+}
+
+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 the same address");
+ res = 1;
+ }
+ if (&protected1 != protected1b_p ())
+ {
+ puts ("`protected1' in main and modb doesn't have the same address");
+ res = 1;
+ }
+
+ /* Check if we get the right protected function symbol. */
+ if (protected1 () != -3)
+ {
+ puts ("`protected1' in main and modb doesn't return the same value");
+ res = 1;
+ }
+
+ /* Check if we get the right function defined in executable. */
+ if (protected2 () != -1)
+ {
+ puts ("`protected2' in main returns the wrong value");
+ res = 1;
+ }
+
+ /* Check `protected1' in moda. */
+ if (!check_protected1 ())
+ {
+ puts ("`protected1' in moda returns the wrong value");
+ res = 1;
+ }
+
+ /* Check `protected2' in moda. */
+ if (!check_protected2 ())
+ {
+ puts ("`protected2' in moda returns the wrong value");
+ res = 1;
+ }
+
+ /* Check if we get the same address for the protected function symbol. */
+ if (&protected3 == protected3a_p ())
+ {
+ puts ("`protected3' in main and moda has the same address");
+ res = 1;
+ }
+ if (&protected3 != protected3b_p ())
+ {
+ puts ("`protected3' in main and modb doesn't have the same address");
+ res = 1;
+ }
+
+ /* Check if we get the right protected function symbol. */
+ if (protected3 () != -5)
+ {
+ puts ("`protected3' in main and modb doesn't return the same value");
+ res = 1;
+ }
+
+ /* Check `protected3' in moda. */
+ if (!check_protected3a ())
+ {
+ puts ("`protected3' in moda returns the wrong value");
+ res = 1;
+ }
+
+ /* Check `protected3' in modb. */
+ if (!check_protected3b ())
+ {
+ puts ("`protected3' in modb returns the wrong value");
+ res = 1;
+ }
+
+ return res;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-protected2bpie.c b/elf/tst-protected2bpie.c
new file mode 100644
index 0000000000..8dcfbd04cb
--- /dev/null
+++ b/elf/tst-protected2bpie.c
@@ -0,0 +1 @@
+#include "tst-protected2b.c"
diff --git a/elf/tst-protected2mod.h b/elf/tst-protected2mod.h
new file mode 100644
index 0000000000..feb28ab0d5
--- /dev/null
+++ b/elf/tst-protected2mod.h
@@ -0,0 +1,35 @@
+/* Test protected function symbols.
+ Copyright (C) 2021 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
+ <https://www.gnu.org/licenses/>. */
+
+/* Prototypes for the functions in the DSOs. */
+extern int protected1 (void);
+extern int protected2 (void);
+extern int protected3 (void);
+
+typedef int (*protected_func_type) (void);
+
+extern protected_func_type protected1a_p (void);
+extern protected_func_type protected1b_p (void);
+
+extern int check_protected1 (void);
+extern int check_protected2 (void);
+
+extern int check_protected3a (void);
+extern protected_func_type protected3a_p (void);
+extern int check_protected3b (void);
+extern protected_func_type protected3b_p (void);
diff --git a/elf/tst-protected2moda.c b/elf/tst-protected2moda.c
new file mode 100644
index 0000000000..db04e8dfb9
--- /dev/null
+++ b/elf/tst-protected2moda.c
@@ -0,0 +1,52 @@
+/* Test protected function symbols.
+ Copyright (C) 2021 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
+ <https://www.gnu.org/licenses/>. */
+
+#include "tst-protected2mod.h"
+
+__attribute__ ((visibility("protected")))
+int
+protected1 (void)
+{
+ return 3;
+}
+
+__attribute__ ((visibility("protected")))
+int
+protected2 (void)
+{
+ return 4;
+}
+
+__attribute__ ((visibility("protected")))
+int
+protected3 (void)
+{
+ return 5;
+}
+
+protected_func_type
+protected1a_p (void)
+{
+ return &protected1;
+}
+
+protected_func_type
+protected3a_p (void)
+{
+ return &protected3;
+}
diff --git a/elf/tst-protected2moda2.c b/elf/tst-protected2moda2.c
new file mode 100644
index 0000000000..fae72177f9
--- /dev/null
+++ b/elf/tst-protected2moda2.c
@@ -0,0 +1,41 @@
+/* Test protected function symbols.
+ Copyright (C) 2021 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
+ <https://www.gnu.org/licenses/>. */
+
+#include "tst-protected2mod.h"
+
+extern int protected1 (void) __attribute__ ((visibility("protected")));
+extern int protected2 (void) __attribute__ ((visibility("protected")));
+extern int protected3 (void) __attribute__ ((visibility("protected")));
+
+int
+check_protected1 (void)
+{
+ return protected1 () == 3;
+}
+
+int
+check_protected2 (void)
+{
+ return protected2 () == 4;
+}
+
+int
+check_protected3a (void)
+{
+ return protected3 () == 5;
+}
diff --git a/elf/tst-protected2modb.c b/elf/tst-protected2modb.c
new file mode 100644
index 0000000000..3c5063f0c3
--- /dev/null
+++ b/elf/tst-protected2modb.c
@@ -0,0 +1,45 @@
+/* Test protected function symbols.
+ Copyright (C) 2021 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include "tst-protected2mod.h"
+
+int
+protected1 (void)
+{
+ return -3;
+}
+
+__attribute__ ((visibility("protected")))
+int
+protected3 (void)
+{
+ return -5;
+}
+
+protected_func_type
+protected1b_p (void)
+{
+ return &protected1;
+}
+
+protected_func_type
+protected3b_p (void)
+{
+ return &protected3;
+}
diff --git a/elf/tst-protected2modb2.c b/elf/tst-protected2modb2.c
new file mode 100644
index 0000000000..b21b827134
--- /dev/null
+++ b/elf/tst-protected2modb2.c
@@ -0,0 +1,28 @@
+/* Test protected function symbols.
+ Copyright (C) 2021 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include "tst-protected2mod.h"
+
+extern int protected3 (void) __attribute__ ((visibility("protected")));
+
+int
+check_protected3b (void)
+{
+ return protected3 () == -5;
+}
--
2.31.1
More information about the Libc-alpha
mailing list