diff options
Diffstat (limited to 'usr/src')
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 |