-
Notifications
You must be signed in to change notification settings - Fork 10.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
lld/coff: Implement some support for the comdat selection field
LLD used to handle comdats as if the selection field was always set to IMAGE_COMDAT_SELECT_ANY. This means for obj files produced by `cl /Gy`, LLD would never report a duplicate symbol error. This change: - adds validation for the Selection field (should make no difference in practice for compiler-generated obj inputs) - rejects comdats that have different Selection fields in different obj files (likewise). This is a bit more strict but also more self-consistent thank link.exe (see comment in code) - implements handling for all the selection kinds In practice, compilers only generate comdats with IMAGE_COMDAT_SELECT_NODUPLICATES (LLD now produces duplicate symbol errors for these), IMAGE_COMDAT_SELECT_ANY (no behavior change), and IMAGE_COMDAT_SELECT_LARGEST (for RTTI data; here LLD should no longer create broken executables when linking some TUs with RTTI enabled and some with it disabled – but see below). The implementation of `IMAGE_COMDAT_SELECT_LARGEST` is incomplete: If one SELECT_LARGEST comdat replaces an earlier one, the comdat symbol is replaced correctly, but the old section stays loaded and if /opt:ref is disabled (via /opt:noref or /debug) it's still written to the output. That's not ideal, but better than the current treatment of just picking any one of those comdats. I hope to fix this better later. Fixes most of PR40094. Differential Revision: https://reviews.llvm.org/D57324 llvm-svn: 352590
- Loading branch information
Showing
6 changed files
with
267 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# REQUIRES: x86 | ||
|
||
# Tests handling of several comdats with "largest" selection type that each | ||
# has an associative comdat. | ||
|
||
# Create obj files. | ||
# RUN: sed -e s/TYPE/.byte/ -e s/SIZE/1/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.1.obj | ||
# RUN: sed -e s/TYPE/.short/ -e s/SIZE/2/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.2.obj | ||
# RUN: sed -e s/TYPE/.long/ -e s/SIZE/4/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.4.obj | ||
|
||
.section .text$ac, "", associative, symbol | ||
assocsym: | ||
.long SIZE | ||
|
||
.section .text$nm, "", largest, symbol | ||
.globl symbol | ||
symbol: | ||
TYPE SIZE | ||
|
||
# Pass the obj files in different orders and check that only the associative | ||
# comdat of the largest obj file makes it into the output, independent of | ||
# the order of the obj files on the command line. | ||
|
||
# FIXME: Make these pass when /opt:noref is passed. | ||
|
||
# RUN: lld-link /include:symbol /dll /noentry /nodefaultlib %t.1.obj %t.2.obj %t.4.obj /out:%t.exe | ||
# RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=ALL124 %s | ||
# ALL124: Contents of section .text: | ||
# ALL124: 180001000 04000000 04000000 .... | ||
|
||
# RUN: lld-link /include:symbol /dll /noentry /nodefaultlib %t.4.obj %t.2.obj %t.1.obj /out:%t.exe | ||
# RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=ALL421 %s | ||
# ALL421: Contents of section .text: | ||
# ALL421: 180001000 04000000 04000000 .... | ||
|
||
# RUN: lld-link /include:symbol /dll /noentry /nodefaultlib %t.2.obj %t.4.obj %t.1.obj /out:%t.exe | ||
# RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=ALL241 %s | ||
# ALL241: Contents of section .text: | ||
# ALL241: 180001000 04000000 04000000 .... | ||
|
||
# RUN: lld-link /include:symbol /dll /noentry /nodefaultlib %t.2.obj %t.1.obj /out:%t.exe | ||
# RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=JUST21 %s | ||
# JUST21: Contents of section .text: | ||
# JUST21: 180001000 02000000 0200 .... | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# REQUIRES: x86 | ||
|
||
# Tests handling of the comdat selection type. | ||
# (Except associative which is tested in associative-comdat.s and | ||
# comdat-selection-associate-largest.s instead.) | ||
|
||
# Create obj files with each selection type. | ||
# RUN: sed -e s/SEL/discard/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.discard.obj | ||
# RUN: sed -e s/SEL/one_only/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.one_only.obj | ||
# RUN: sed -e s/SEL/same_size/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.same_size.obj | ||
# RUN: sed -e s/SEL/same_size/ -e s/.long/.short/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.same_size.short.obj | ||
# RUN: sed -e s/SEL/same_contents/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.same_contents.obj | ||
# RUN: sed -e s/SEL/same_contents/ -e s/.long/.short/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.same_contents.short.obj | ||
# RUN: sed -e s/SEL/same_contents/ -e s/1/2/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.same_contents.2.obj | ||
# RUN: sed -e s/SEL/largest/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.largest.obj | ||
# RUN: sed -e s/SEL/largest/ -e s/.long/.short/ -e s/1/2/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.largest.short.2.obj | ||
# RUN: sed -e s/SEL/newest/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.newest.obj | ||
|
||
.section .text$nm, "", SEL, symbol | ||
.globl symbol | ||
symbol: | ||
.long 1 | ||
|
||
# First, pass each selection type twice. All should link fine except for | ||
# one_only which should report a duplicate symbol error and newest which | ||
# link.exe (and hence lld-link) doesn't understand. | ||
|
||
# RUN: cp %t.discard.obj %t.obj && lld-link /dll /noentry /nodefaultlib %t.discard.obj %t.obj | ||
# RUN: cp %t.one_only.obj %t.obj && not lld-link /dll /noentry /nodefaultlib %t.one_only.obj %t.obj 2>&1 | FileCheck --check-prefix=ONEONE %s | ||
# ONEONE: lld-link: error: duplicate symbol: symbol | ||
# RUN: cp %t.same_size.obj %t.obj && lld-link /dll /noentry /nodefaultlib %t.same_size.obj %t.obj | ||
# RUN: cp %t.same_contents.obj %t.obj && lld-link /dll /noentry /nodefaultlib %t.same_contents.obj %t.obj | ||
# RUN: cp %t.largest.obj %t.obj && lld-link /dll /noentry /nodefaultlib %t.largest.obj %t.obj | ||
# RUN: cp %t.newest.obj %t.obj && not lld-link /dll /noentry /nodefaultlib %t.newest.obj %t.obj 2>&1 | FileCheck --check-prefix=NEWNEW %s | ||
# NEWNEW: lld-link: error: unknown comdat type 7 for symbol | ||
|
||
# /force doesn't affect errors about unknown comdat types. | ||
# RUN: cp %t.newest.obj %t.obj && not lld-link /force /dll /noentry /nodefaultlib %t.newest.obj %t.obj 2>&1 | FileCheck --check-prefix=NEWNEWFORCE %s | ||
# NEWNEWFORCE: lld-link: error: unknown comdat type 7 for symbol | ||
|
||
# Check that same_size, same_contents, largest do what they're supposed to. | ||
|
||
# Check that the "same_size" selection produces an error if passed two symbols | ||
# with different size. | ||
# RUN: not lld-link /dll /noentry /nodefaultlib %t.same_size.obj %t.same_size.short.obj 2>&1 | FileCheck --check-prefix=SAMESIZEDUPE %s | ||
# SAMESIZEDUPE: lld-link: error: duplicate symbol: symbol | ||
|
||
# Check that the "same_contents" selection produces an error if passed two | ||
# symbols with different contents. | ||
# RUN: not lld-link /dll /noentry /nodefaultlib %t.same_contents.obj %t.same_contents.2.obj 2>&1 | FileCheck --check-prefix=SAMECONTENTSDUPE1 %s | ||
# SAMECONTENTSDUPE1: lld-link: error: duplicate symbol: symbol | ||
# RUN: not lld-link /dll /noentry /nodefaultlib %t.same_contents.obj %t.same_contents.2.obj 2>&1 | FileCheck --check-prefix=SAMECONTENTSDUPE2 %s | ||
# SAMECONTENTSDUPE2: lld-link: error: duplicate symbol: symbol | ||
|
||
# Check that the "largest" selection picks the larger comdat (independent of | ||
# the order the .obj files are passed on the commandline). | ||
# RUN: lld-link /opt:noref /include:symbol /dll /noentry /nodefaultlib %t.largest.obj %t.largest.short.2.obj /out:%t.exe | ||
# RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=LARGEST1 %s | ||
# LARGEST1: Contents of section .text: | ||
# LARGEST1: 180001000 01000000 .... | ||
|
||
# FIXME: Make this pass when /opt:noref is passed. | ||
# RUN: lld-link /include:symbol /dll /noentry /nodefaultlib %t.largest.short.2.obj %t.largest.obj /out:%t.exe | ||
# RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=LARGEST2 %s | ||
# LARGEST2: Contents of section .text: | ||
# LARGEST2: 180001000 01000000 .... | ||
|
||
|
||
# Test linking the same symbol with different comdat selection types. | ||
# link.exe generally rejects this, except for "largest" which is allowed to | ||
# combine with everything (https://bugs.llvm.org/show_bug.cgi?id=40094#c7). | ||
# lld-link rejects all comdat selection type mismatches. Spot-test just a few | ||
# combinations. | ||
|
||
# RUN: not lld-link /dll /noentry /nodefaultlib %t.discard.obj %t.one_only.obj 2>&1 | FileCheck --check-prefix=DISCARDONE %s | ||
# DISCARDONE: lld-link: error: conflicting comdat type for symbol: 2 in | ||
# RUN: lld-link /force /dll /noentry /nodefaultlib %t.discard.obj %t.one_only.obj 2>&1 | FileCheck --check-prefix=DISCARDONEFORCE %s | ||
# DISCARDONEFORCE: lld-link: warning: conflicting comdat type for symbol: 2 in | ||
|
||
# RUN: not lld-link /dll /noentry /nodefaultlib %t.same_contents.obj %t.same_size.obj 2>&1 | FileCheck --check-prefix=CONTENTSSIZE %s | ||
# CONTENTSSIZE: lld-link: error: conflicting comdat type for symbol: 4 in | ||
|
||
# These cases are accepted by link.exe but not by lld-link. | ||
# RUN: not lld-link /dll /noentry /nodefaultlib %t.discard.obj %t.largest.obj 2>&1 | FileCheck --check-prefix=DISCARDLARGEST %s | ||
# DISCARDLARGEST: lld-link: error: conflicting comdat type for symbol: 2 in | ||
# RUN: not lld-link /dll /noentry /nodefaultlib %t.largest.obj %t.one_only.obj 2>&1 | FileCheck --check-prefix=LARGESTONE %s | ||
# LARGESTONE: lld-link: error: conflicting comdat type for symbol: 6 in |