summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/sgs/libld/common/syms.c38
-rw-r--r--usr/src/cmd/sgs/tools/SUNWonld-README1
-rw-r--r--usr/src/pkg/manifests/system-test-elftest.p5m12
-rw-r--r--usr/src/test/elf-tests/runfiles/default.run4
-rw-r--r--usr/src/test/elf-tests/tests/Makefile1
-rw-r--r--usr/src/test/elf-tests/tests/resolution/Makefile19
-rw-r--r--usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/Makefile49
-rw-r--r--usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/Makefile.test42
-rw-r--r--usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/README.md40
-rw-r--r--usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/access.S17
-rw-r--r--usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/hidden.s20
-rw-r--r--usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/main.c48
-rw-r--r--usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/mixed-hidden-comdat.sh71
-rw-r--r--usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/visible.s13
14 files changed, 372 insertions, 3 deletions
diff --git a/usr/src/cmd/sgs/libld/common/syms.c b/usr/src/cmd/sgs/libld/common/syms.c
index ff073c9aa7..88f3ed7fa9 100644
--- a/usr/src/cmd/sgs/libld/common/syms.c
+++ b/usr/src/cmd/sgs/libld/common/syms.c
@@ -2637,7 +2637,7 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl)
if (shndx >= ifl->ifl_shnum) {
/*
- * Carry our some basic sanity checks
+ * Carry out some basic sanity checks.
* The symbol will not be carried forward to
* the output file, which won't be a problem
* unless a relocation is required against it.
@@ -2652,7 +2652,40 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl)
}
isp = ifl->ifl_isdesc[shndx];
- if (isp && (isp->is_flags & FLG_IS_DISCARD)) {
+ if ((isp != NULL) &&
+ (isp->is_flags & FLG_IS_DISCARD) &&
+ (isp->is_flags & FLG_IS_COMDAT)) {
+ Sym *rsym;
+
+ /*
+ * Replace the original symbol definition with
+ * a symbol reference, so that resolution can
+ * occur.
+ *
+ * It is common due to compiler issues or
+ * build system intricacy for COMDAT groups to
+ * refer to symbols of different visibility,
+ * even though this is erroneous. By
+ * replacing the discarded members of these
+ * groups with symbol references we allow
+ * symbol resolution to occur and the most
+ * restrictive visibility to be chosen.
+ */
+ if ((rsym = libld_malloc(sizeof (Sym))) == NULL)
+ return (S_ERROR);
+
+ *rsym = *nsym;
+ rsym->st_shndx = shndx = SHN_UNDEF;
+ rsym->st_value = 0x0;
+ rsym->st_size = 0x0;
+
+ nsym = rsym;
+
+ sdflags |= FLG_SY_ISDISC;
+ DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp));
+ } else if ((isp != NULL) &&
+ (isp->is_flags & FLG_IS_DISCARD)) {
+ /* Discarded but not via COMDAT */
if ((sdp =
libld_calloc(sizeof (Sym_desc), 1)) == NULL)
return (S_ERROR);
@@ -2668,7 +2701,6 @@ ld_sym_process(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl)
sdp->sd_isc = isp;
sdp->sd_flags = FLG_SY_ISDISC;
ifl->ifl_oldndx[ndx] = sdp;
-
DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp));
continue;
}
diff --git a/usr/src/cmd/sgs/tools/SUNWonld-README b/usr/src/cmd/sgs/tools/SUNWonld-README
index bce5091fb1..50f2f457dc 100644
--- a/usr/src/cmd/sgs/tools/SUNWonld-README
+++ b/usr/src/cmd/sgs/tools/SUNWonld-README
@@ -1681,3 +1681,4 @@ Bugid Risk Synopsis
14157 ld(1) string table merging should follow gABI more closely
14207 want updated ELF relocation definitions from the psABI
14209 partial support for new relaxable relocations
+14250 ld should resolve discarded COMDAT symbols against their mates
diff --git a/usr/src/pkg/manifests/system-test-elftest.p5m b/usr/src/pkg/manifests/system-test-elftest.p5m
index a118845014..b06db1898b 100644
--- a/usr/src/pkg/manifests/system-test-elftest.p5m
+++ b/usr/src/pkg/manifests/system-test-elftest.p5m
@@ -85,6 +85,18 @@ dir path=opt/elf-tests/tests/relocs/i386
dir path=opt/elf-tests/tests/relocs/i386/got32x
file path=opt/elf-tests/tests/relocs/i386/got32x/got32x mode=0555
file path=opt/elf-tests/tests/relocs/i386/got32x/got32x.s mode=0444
+dir path=opt/elf-tests/tests/resolution
+dir path=opt/elf-tests/tests/resolution/mixed-hidden-comdat
+file path=opt/elf-tests/tests/resolution/mixed-hidden-comdat/Makefile.test \
+ mode=0444
+file path=opt/elf-tests/tests/resolution/mixed-hidden-comdat/README.md mode=0444
+file path=opt/elf-tests/tests/resolution/mixed-hidden-comdat/access.S mode=0444
+file path=opt/elf-tests/tests/resolution/mixed-hidden-comdat/hidden.s mode=0444
+file path=opt/elf-tests/tests/resolution/mixed-hidden-comdat/main.c mode=0444
+file \
+ path=opt/elf-tests/tests/resolution/mixed-hidden-comdat/mixed-hidden-comdat \
+ mode=0555
+file path=opt/elf-tests/tests/resolution/mixed-hidden-comdat/visible.s mode=0444
dir path=opt/elf-tests/tests/string-merge
file path=opt/elf-tests/tests/string-merge/simple mode=0555
file path=opt/elf-tests/tests/string-merge/str1.s mode=0444
diff --git a/usr/src/test/elf-tests/runfiles/default.run b/usr/src/test/elf-tests/runfiles/default.run
index c8cf538678..8ca7471a9e 100644
--- a/usr/src/test/elf-tests/runfiles/default.run
+++ b/usr/src/test/elf-tests/runfiles/default.run
@@ -40,6 +40,10 @@ tests = ['got32x']
arch = i86pc
tests = ['gotpcrelx', 'rex_gotpcrelx']
+[/opt/elf-tests/tests/resolution/mixed-hidden-comdat]
+arch = i86pc
+tests = ['mixed-hidden-comdat']
+
[/opt/elf-tests/tests/string-merge/]
tests = ['simple']
diff --git a/usr/src/test/elf-tests/tests/Makefile b/usr/src/test/elf-tests/tests/Makefile
index 416717de12..860577dd3c 100644
--- a/usr/src/test/elf-tests/tests/Makefile
+++ b/usr/src/test/elf-tests/tests/Makefile
@@ -19,6 +19,7 @@ SUBDIRS = \
linker-sets \
mapfiles \
relocs \
+ resolution \
string-merge \
tls
diff --git a/usr/src/test/elf-tests/tests/resolution/Makefile b/usr/src/test/elf-tests/tests/resolution/Makefile
new file mode 100644
index 0000000000..8936d5a72b
--- /dev/null
+++ b/usr/src/test/elf-tests/tests/resolution/Makefile
@@ -0,0 +1,19 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+# Copyright 2018 Joyent, Inc.
+#
+
+SUBDIRS = mixed-hidden-comdat
+
+include $(SRC)/test/Makefile.com
diff --git a/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/Makefile b/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/Makefile
new file mode 100644
index 0000000000..0739679b7a
--- /dev/null
+++ b/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/Makefile
@@ -0,0 +1,49 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+# Copyright 2021, Richard Lowe.
+
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/test/Makefile.com
+
+PROG = mixed-hidden-comdat
+
+DATAFILES = access.S hidden.s main.c visible.s Makefile.test README.md
+
+ROOTOPTPKG = $(ROOT)/opt/elf-tests
+TESTDIR = $(ROOTOPTPKG)/tests/resolution/mixed-hidden-comdat
+
+CMDS = $(PROG:%=$(TESTDIR)/%)
+$(CMDS) := FILEMODE = 0555
+
+DATA = $(DATAFILES:%=$(TESTDIR)/%)
+$(DATA) := FILEMODE = 0444
+
+all:
+
+install: all $(CMDS) $(DATA)
+
+clobber: clean
+ -$(RM) $(PROG)
+
+clean:
+ -$(RM) $(CLEANFILES)
+
+$(CMDS): $(TESTDIR)
+
+$(TESTDIR):
+ $(INS.dir)
+
+$(TESTDIR)/%: %.sh
+ $(INS.rename)
+
+$(TESTDIR)/%: %
+ $(INS.file)
diff --git a/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/Makefile.test b/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/Makefile.test
new file mode 100644
index 0000000000..525939238c
--- /dev/null
+++ b/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/Makefile.test
@@ -0,0 +1,42 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+# Copyright 2021, Richard Lowe.
+
+OBJS=visible.o hidden.o access.o
+
+SRCDIR=$(PWD)
+
+.KEEP_STATE:
+
+all: libnoref.so libothertest.so test
+
+%.o: $(SRCDIR)/%.s
+ gcc -D_ASM -m64 -c $< -o $@
+%.o: $(SRCDIR)/%.S
+ gcc -D_ASM -m64 -c $< -o $@
+
+libtest.so: $(OBJS)
+ gcc -m64 -shared $(OBJS) -o $@
+
+# libtest.so, but with the important objects in the other order so that we
+# choose the other COMDAT section to keep.
+libothertest.so: $(OBJS)
+ gcc -m64 -shared hidden.o visible.o access.o -o $@
+
+libnoref.so: $(OBJS:access.o=) #Remove any references
+ gcc -m64 -Wl,-zignore -shared $(OBJS:access.o=) -o $@
+
+test: $(SRCDIR)/main.c libtest.so
+ gcc -m64 $(SRCDIR)/main.c -o $@ -L$(PWD) -R$(PWD) -ltest
+
+clean:
+ rm -rf $(OBJS) test libtest.so
diff --git a/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/README.md b/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/README.md
new file mode 100644
index 0000000000..c6dc37eecd
--- /dev/null
+++ b/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/README.md
@@ -0,0 +1,40 @@
+This is a test that COMDAT sections with differing visibilities get resolved
+to the most restrictive visibility, by the usual rules of symbol
+resolution.
+
+The GNU compiler, or build systems which use `-fvisibility*` inconsistently
+often emit technically incorrect COMDAT sections where by the sections are not
+strictly equivalent because they differ in visibility. This tests that we
+resolve, and resolve them to the most restrictive visibility as the compiler
+expects.
+
+We do this...
+
+- `visible.s`
+ defines our two COMDAT symbols/sections (`data_symbol` and `bss_symbol`)
+ with default visibility
+
+- `hidden.s`
+ defines our two COMDAT symbols/sections (`data_symbol` and
+ `bss_symbol`) with hidden visibility
+
+- `access.S`
+ provides access to our data using relocations we control,
+ just in case
+
+- `main.c`
+ an actual test wrapper that just checks the values of the
+ data
+
+- `Makefile.test`
+ A Makefile to build the tests on the system under test
+
+...and check that the resulting `test` binary links and runs.
+
+For an added check we intentionally break the COMDAT rules ourselves, and know
+a little bit about the link-editor implementation. `hidden.s` and `visible.s`
+give `data_symbol` _different values_. We know based on the link-editor
+implementation that the first section seen will be the one taken by the
+link-editor, so we check for the value from `data.s`, but implicitly rely on the
+_visibility_ from `hidden.s` to link. Proving to ourselves that the visibility
+came from symbol resolution and not any other means.
diff --git a/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/access.S b/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/access.S
new file mode 100644
index 0000000000..981f47a105
--- /dev/null
+++ b/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/access.S
@@ -0,0 +1,17 @@
+#include <sys/asm_linkage.h>
+
+ENTRY_NP(test_data)
+ pushq %rbp
+ movq %rsp, %rbp
+ movq data_symbol(%rip), %rax
+ leave
+ ret
+SET_SIZE(test_data)
+
+ENTRY_NP(test_bss)
+ pushq %rbp
+ movq %rsp, %rbp
+ movq bss_symbol(%rip), %rax
+ leave
+ ret
+SET_SIZE(test_bss)
diff --git a/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/hidden.s b/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/hidden.s
new file mode 100644
index 0000000000..fbf0b565bf
--- /dev/null
+++ b/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/hidden.s
@@ -0,0 +1,20 @@
+ .type bss_symbol, @object
+ .section .bss.bss_symbol,"awG",@nobits,bss_symbol,comdat
+ .hidden bss_symbol
+ .weak bss_symbol
+ .size bss_symbol, 8
+bss_symbol:
+ .zero 8
+
+ .type data_symbol, @object
+ .section .data.data_symbol,"awG",@progbits,data_symbol,comdat
+ .hidden data_symbol
+ .weak data_symbol
+ .size data_symbol, 8
+ /*
+ * Intentionally break the COMDAT rules and give this a different
+ * value, so we can assert that the value got from one place and the
+ * visibility resolved from the other
+ */
+data_symbol:
+ .zero 8
diff --git a/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/main.c b/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/main.c
new file mode 100644
index 0000000000..d93fc0f9c1
--- /dev/null
+++ b/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/main.c
@@ -0,0 +1,48 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2021, Richard Lowe.
+ */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+extern uint64_t test_data(void);
+extern uint64_t test_bss(void);
+
+#define CORRECT_DATA 8675309
+#define CORRECT_BSS 0
+
+int
+main(int argc, char **argv)
+{
+ uint64_t td = test_data();
+ uint64_t tb = test_bss();
+
+ if (td != CORRECT_DATA) {
+ printf("FAIL: test data mismatch: should be %ld is %ld\n",
+ CORRECT_DATA, td);
+ abort();
+ }
+
+ if (tb != CORRECT_BSS) {
+ printf("FAIL: test bss mismatch: should be %ld is %ld\n",
+ CORRECT_BSS, tb);
+ abort();
+ }
+
+ printf("SUCCESS\n");
+
+ return (0);
+}
diff --git a/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/mixed-hidden-comdat.sh b/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/mixed-hidden-comdat.sh
new file mode 100644
index 0000000000..5d11cc67df
--- /dev/null
+++ b/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/mixed-hidden-comdat.sh
@@ -0,0 +1,71 @@
+#!/bin/ksh
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+# Copyright 2021, Richard Lowe.
+
+TESTDIR=$(dirname $0)
+
+tmpdir=/tmp/test.$$
+mkdir $tmpdir
+cd $tmpdir
+
+cleanup() {
+ cd /
+ rm -fr $tmpdir
+}
+
+trap 'cleanup' EXIT
+
+if [[ $PWD != $tmpdir ]]; then
+ print -u2 "Failed to create temporary directory: $tmpdir"
+ exit 1;
+fi
+
+make -f ${TESTDIR}/Makefile.test SRCDIR=${TESTDIR}
+if (( $? != 0 )); then
+ print -u2 "FAIL: Failed to link"
+ exit 1;
+fi
+
+elfdump -sN.symtab libtest.so | awk '$9 ~ /(bss|data)_symbol/ {
+ if ($5 != "LOCL") {
+ exit 1;
+ }
+}'
+
+if (( $? != 0 )); then
+ print -u2 "FAIL: libtest.so COMDAT symbols not reduced to local"
+ exit 1;
+fi
+
+elfdump -sN.symtab libothertest.so | awk '$9 ~ /(bss|data)_symbol/ {
+ if ($5 != "LOCL") {
+ exit 1;
+ }
+}'
+
+if (( $? != 0 )); then
+ print -u2 "FAIL: libothertest.so COMDAT symbols not reduced to local"
+ exit 1;
+fi
+
+elfdump -s libnoref.so | grep -q _symbol
+if (( $? == 0 )); then
+ print -u2 "FAIL: unreferenced symbols survive into output object"
+ exit 1;
+fi
+
+./test
+if (( $? != 0 )); then
+ print -u2 "FAIL: Failed to execute ./test"
+ exit 1;
+fi
diff --git a/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/visible.s b/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/visible.s
new file mode 100644
index 0000000000..67a293e669
--- /dev/null
+++ b/usr/src/test/elf-tests/tests/resolution/mixed-hidden-comdat/visible.s
@@ -0,0 +1,13 @@
+ .type bss_symbol, @object
+ .section .bss.bss_symbol,"awG",@nobits,bss_symbol,comdat
+ .weak bss_symbol
+ .size bss_symbol, 8
+bss_symbol:
+ .zero 8
+
+ .type data_symbol, @object
+ .section .data.data_symbol,"awG",@progbits,data_symbol,comdat
+ .weak data_symbol
+ .size data_symbol, 8
+data_symbol:
+ .quad 8675309