Text file src/cmd/go/testdata/script/cgo_suspect_flag_force_external.txt

     1  # Test case to verify that when we have a package that uses CGO in
     2  # combination with selected "unusual" flags (involving plugins, LTO)
     3  # that we force external linking.  See related
     4  # issues 58619,  58620, and 58848.
     5  
     6  [compiler:gccgo] skip # only external linking for gccgo
     7  
     8  [!cgo] skip 'test verifies behavior that depends on CGO_CFLAGS'
     9  [mustlinkext] skip 'test expects internal linking for non-cgo programs'
    10  
    11  # Here we build three program: one with explicit CGO use, one with no
    12  # CGO use, and one that uses a stdlib package ("runtime/cgo") that has
    13  # CGO in it. It used to be that only the explicit use of CGO would
    14  # trigger external linking, and that the program that only used
    15  # "runtime/cgo" would always be handled with internal linking. This caused
    16  # issues when users included odd/unusual flags (ex: -fplugin, -flto)
    17  # in CGO_CFLAGS, causing the Go linker to have to read and interpret
    18  # non-standard host objects.
    19  #
    20  # As of 1.21 we continue to use internal linking for programs whose
    21  # CGO use comes only from stdlib packages in the absence of any flag
    22  # funny business, however if the Go command sees flags that may be suspicious,
    23  # it signals the Go linker to invoke the external linker.
    24  
    25  # The next few tests run builds passing "-n" to the Go command, then
    26  # checking the output to see if the Go command is trying to pass a
    27  # "preferlinkext" token to the linker to request external linking.
    28  
    29  #-----------------------
    30  
    31  # Use a fresh GOCACHE for these next steps, so as to have the real
    32  # actions for the runtime/cgo package appear in the "-n -x" output.
    33  env GOCACHE=$WORK/gocache
    34  mkdir $GOCACHE
    35  
    36  # First build: there is no CGO in use, so no token should be present regardless
    37  # of weird CGO flags.
    38  go build -x -n -o dummy.exe ./noUseOfCgo
    39  ! stderr preferlinkext
    40  env CGO_CFLAGS=-flto
    41  go build -x -n -o dummy.exe ./noUseOfCgo
    42  ! stderr preferlinkext
    43  env CGO_CFLAGS=
    44  
    45  # Second build uses CGO, so we expect to see the token present in the
    46  # -n output only when strange flags are used.
    47  go build -x -n -o dummy.exe ./usesInternalCgo
    48  ! stderr preferlinkext
    49  env CGO_CFLAGS=-flto
    50  go build -x -n -o dummy.exe ./usesInternalCgo
    51  stderr preferlinkext
    52  env CGO_CFLAGS=-fplugin
    53  go build -x -n -o dummy.exe ./usesInternalCgo
    54  stderr preferlinkext
    55  env CGO_CFLAGS=-fprofile-instr-generate
    56  go build -x -n -o dummy.exe ./usesInternalCgo
    57  stderr preferlinkext
    58  
    59  # Trimming file information for the UndefinedBehaviorSanitizer is permitted for internal linking.
    60  env CGO_CFLAGS=-fsanitize-undefined-strip-path-components=-1
    61  go build -x -n -o dummy.exe ./usesInternalCgo
    62  ! stderr preferlinkext
    63  env CGO_CFLAGS=-fsanitize-undefined-strip-path-components=2
    64  go build -x -n -o dummy.exe ./usesInternalCgo
    65  ! stderr preferlinkext
    66  
    67  # The -fdebug-prefix-map=path is permitted for internal linking.
    68  env CGO_CFLAGS=-fdebug-prefix-map=/some/sandbox/execroot/workspace=/tmp/new
    69  go build -x -n -o dummy.exe ./usesInternalCgo
    70  ! stderr preferlinkext
    71  env CGO_CFLAGS=-fdebug-prefix-map=/Users/someone/.cache/bazel/_bazel_someone/3fa7e4650c43657ead684537951f49e2/sandbox/linux-sandbox/10/execroot/rules_go_static=.
    72  go build -x -n -o dummy.exe ./usesInternalCgo
    73  ! stderr preferlinkext
    74  # The -ffile-prefix-map=path is permitted for internal linking too.
    75  env CGO_CFLAGS=-ffile-prefix-map=/Users/someone/.cache/bazel/_bazel_someone/3fa7e4650c43657ead684537951f49e2/sandbox/linux-sandbox/10/execroot/rules_go_static/bazel-out/aarch64-fastbuild-ST-b33d65c724e6/bin/external/io_bazel_rules_go/stdlib_=.
    76  go build -x -n -o dummy.exe ./usesInternalCgo
    77  ! stderr preferlinkext
    78  # Verifying that -fdebug-prefix-map=path, -ffile-prefix-map, -no-canonical-prefixes
    79  # and -fno-canonical-systemd-headers are permitted for internal linking.
    80  env CGO_CFLAGS=-fdebug-prefix-map=old=/tmp/new
    81  go build -x -n -o dummy.exe ./usesInternalCgo
    82  ! stderr preferlinkext
    83  env CGO_CFLAGS=-ffile-prefix-map=/Users/someone/_11233/things=new
    84  go build -x -n -o dummy.exe ./usesInternalCgo
    85  ! stderr preferlinkext
    86  env CGO_CFLAGS=-no-canonical-prefixes
    87  go build -x -n -o dummy.exe ./usesInternalCgo
    88  ! stderr preferlinkext
    89  env CGO_CFLAGS=-fno-canonical-system-headers
    90  go build -x -n -o dummy.exe ./usesInternalCgo
    91  ! stderr preferlinkext
    92  env CGO_CFLAGS=
    93  
    94  # CGO_LDFLAGS with -static variants are not compatible with internal linking.
    95  env CGO_LDFLAGS=-static
    96  go build -x -n -o dummy.exe ./usesInternalCgo
    97  stderr preferlinkext
    98  env CGO_LDFLAGS=--static
    99  go build -x -n -o dummy.exe ./usesInternalCgo
   100  stderr preferlinkext
   101  env CGO_LDFLAGS=-Wl,-static
   102  go build -x -n -o dummy.exe ./usesInternalCgo
   103  stderr preferlinkext
   104  env CGO_LDFLAGS=-Wl,--static
   105  go build -x -n -o dummy.exe ./usesInternalCgo
   106  stderr preferlinkext
   107  env CGO_LDFLAGS=-Wl,-Bstatic
   108  go build -x -n -o dummy.exe ./usesInternalCgo
   109  stderr preferlinkext
   110  env CGO_LDFLAGS=
   111  
   112  # CGO_LDFLAGS=-static-libgcc does NOT trigger external linking.
   113  env CGO_LDFLAGS=-static-libgcc
   114  go build -x -n -o dummy.exe ./usesInternalCgo
   115  ! stderr preferlinkext
   116  env CGO_LDFLAGS=
   117  
   118  # CGO_CFLAGS=--static triggers external linking (some toolchains accept it).
   119  env CGO_CFLAGS=--static
   120  go build -x -n -o dummy.exe ./usesInternalCgo
   121  stderr preferlinkext
   122  env CGO_CFLAGS=
   123  
   124  [short] skip
   125  
   126  # In the remaining tests below we do actual builds (without -n) to
   127  # verify that the Go linker is going the right thing in addition to the
   128  # Go command. Here the idea is to pass "-tmpdir" to the linker, then
   129  # check after the link is done for the presence of the file
   130  # <tmpdir>/go.o, which the Go linker creates prior to kicking off the
   131  # external linker.
   132  
   133  mkdir tmp1
   134  mkdir tmp2
   135  mkdir tmp3
   136  mkdir tmp4
   137  mkdir tmp5
   138  
   139  # First build: no external linking expected
   140  go build -ldflags=-tmpdir=tmp1 -o $devnull ./noUseOfCgo &
   141  
   142  # Second build: using only "runtime/cgo", expect internal linking.
   143  go build -ldflags=-tmpdir=tmp2 -o $devnull ./usesInternalCgo &
   144  
   145  # Third build: program uses only "runtime/cgo", so we would normally
   146  # expect internal linking, except that cflags contain suspicious entries
   147  # (in this case, a flag that does not appear on the allow list).
   148  env CGO_CFLAGS=-fmerge-all-constants
   149  env CGO_LDFLAGS=-fmerge-all-constants
   150  go build -ldflags=-tmpdir=tmp3 -o $devnull ./usesInternalCgo &
   151  env CGO_CFLAGS=
   152  env CGO_LDFLAGS=
   153  
   154  # Fourth build: explicit CGO, expect external linking.
   155  go build -ldflags=-tmpdir=tmp4 -o $devnull ./usesExplicitCgo &
   156  
   157  # Fifth build: explicit CGO, but we specifically asked for internal linking
   158  # via a flag, so using internal linking it is.
   159  [cgolinkext] go list ./usesInternalCgo
   160  [!cgolinkext] go build '-ldflags=-tmpdir=tmp5 -linkmode=internal' -o $devnull ./usesInternalCgo &
   161  
   162  # Sixth build: explicit CGO use in a non-main package.
   163  go build -o p.a ./nonMainPackageUsesExplicitCgo &
   164  
   165  wait
   166  
   167  # Check first build: no external linking expected
   168  ! exists tmp1/go.o
   169  
   170  # Check second build: using only "runtime/cgo", expect internal linking.
   171  [!cgolinkext] ! exists tmp2/go.o
   172  [cgolinkext] exists tmp2/go.o
   173  
   174  # Check third build: has suspicious flag.
   175  exists tmp3/go.o
   176  
   177  # Fourth build: explicit CGO, expect external linking.
   178  exists tmp4/go.o
   179  
   180  # Fifth build: explicit CGO, -linkmode=internal.
   181  ! exists tmp5/go.o
   182  
   183  # Sixth build: make sure that "go tool nm" doesn't get confused
   184  # by the presence of the "preferlinkext" sentinel.
   185  go tool nm p.a
   186  
   187  -- go.mod --
   188  
   189  module cgo.example
   190  
   191  go 1.20
   192  
   193  -- noUseOfCgo/main.go --
   194  
   195  package main
   196  
   197  func main() {
   198  	println("clean as a whistle")
   199  }
   200  
   201  -- usesInternalCgo/main.go --
   202  
   203  package main
   204  
   205  import (
   206  	"runtime/cgo"
   207  )
   208  
   209  func main() {
   210  	q := "hello"
   211  	h := cgo.NewHandle(q)
   212  	h.Delete()
   213  }
   214  
   215  -- usesExplicitCgo/main.go --
   216  
   217  package main
   218  
   219  /*
   220  int meaningOfLife() { return 42; }
   221  */
   222  import "C"
   223  
   224  func main() {
   225       println(C.meaningOfLife())
   226  }
   227  
   228  -- nonMainPackageUsesExplicitCgo/main.go --
   229  
   230  package p
   231  
   232  /*
   233  int meaningOfLife() { return 42; }
   234  */
   235  import "C"
   236  
   237  func PrintIt() {
   238       println(C.meaningOfLife())
   239  }
   240  

View as plain text