Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/link: -buildmode=c-shared exports many functions, not just //export functions #30674

Closed
GameXG opened this issue Mar 8, 2019 · 10 comments
Closed
Labels
FrozenDueToAge help wanted NeedsFix The path to resolution is known, but the work has not been done. OS-Windows
Milestone

Comments

@GameXG
Copy link

GameXG commented Mar 8, 2019

What version of Go are you using (go version)?

$ go version
go version go1.12 windows/amd64

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env

set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\gamexg\AppData\Local\go-build
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=D:\golang
set GOPROXY=
set GORACE=
set GOROOT=C:\Go
set GOTMPDIR=
set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
set GCCGO=gccgo
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\gamexg\AppData\Local\Temp\go-build864381234=/tmp/go-build -gno-record-gcc-switches

What did you do?

>go build  -ldflags "-s -w"  -buildmode=c-shared -o libhello.dll hello.go
// file hello.go
package main

// //Needed for build
import "C"

import (
	"fmt"

	"go.uber.org/zap"
)

//export SayHello
func SayHello(name string) {
	fmt.Printf("func in Golang SayHello says: Hello, %s!\n", name)
}

//export Test
func Test() {
	logger, _ := zap.NewProduction()
	logger.Error("err")
}

func main() {
	// We need the main function to make possible
	// CGO compiler to compile the package as C shared library
}

What did you expect to see?

>dumpbin -exports libhello.dll
Microsoft (R) COFF/PE Dumper Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file libhello.dll

File Type: DLL

  Section contains the following exports for libhello.dll

    00000000 characteristics
    5C7FB64A time date stamp Wed Mar  6 20:00:10 2019
        0.00 version
           1 ordinal base
        3320 number of functions
        3320 number of names

    ordinal hint RVA      name

          1    0 0024B8C0 SayHello
          2    1 0024B910 Test

What did you see instead?

> dumpbin -exports libhello.dll
Microsoft (R) COFF/PE Dumper Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file libhello.dll

File Type: DLL

  Section contains the following exports for libhello.dll

    00000000 characteristics
    5C822141 time date stamp Fri Mar  8 16:01:05 2019
        0.00 version
           1 ordinal base
        8462 number of functions
        8462 number of names

    ordinal hint RVA      name

          1    0 0024B8C0 SayHello
          2    1 0024B910 Test
          3    2 0024BC00 _cgo_get_context_function
          4    3 00278768 _cgo_init
          5    4 0024BAA0 _cgo_is_runtime_initialized
          6    5 0024B9E0 _cgo_maybe_run_preinit
          7    6 00278770 _cgo_notify_runtime_init_done
          8    7 0005E040 _cgo_panic
          9    8 0024B980 _cgo_preinit_init
         10    9 0024B950 _cgo_release_context
         11    A 00278778 _cgo_sys_thread_create
         12    B 0024BCF0 _cgo_sys_thread_start
         13    C 00278780 _cgo_thread_start
         14    D 00057640 _cgo_topofstack
         15    E 0024BAD0 _cgo_wait_runtime_init_done
         16    F 00518760 _cgo_yield
         17   10 0024B5F0 _cgoexp_ad639554f05a_SayHello
         18   11 0024B720 _cgoexp_ad639554f05a_Test
         19   12 00058E50 _rt0_amd64_windows_lib
         20   13 00278748 _rt0_amd64_windows_lib.ptr
         21   14 00058EB0 _rt0_amd64_windows_lib_go
         22   15 001DFFC0 bufio.(*Reader).Discard
         23   16 001DFDC0 bufio.(*Reader).Peek
         24   17 001E0120 bufio.(*Reader).Read
         25   18 001E0520 bufio.(*Reader).ReadByte
         26   19 001E08E0 bufio.(*Reader).ReadLine
         27   1A 001E06A0 bufio.(*Reader).ReadSlice
         28   1B 001DFB80 bufio.(*Reader).Size
         29   1C 001E0600 bufio.(*Reader).UnreadByte
         30   1D 001E0B30 bufio.(*Reader).WriteTo
         31   1E 001DFB90 bufio.(*Reader).fill
         32   1F 001E0E60 bufio.(*Reader).writeBuf
         33   20 001E0F70 bufio.(*Writer).Flush
         34   21 001E1640 bufio.(*Writer).ReadFrom
         35   22 001E0F60 bufio.(*Writer).Size
         36   23 001E1150 bufio.(*Writer).Write
         37   24 001E13A0 bufio.(*Writer).WriteByte
         38   25 001E1470 bufio.(*Writer).WriteString
         39   26 0051BA80 bufio.ErrAdvanceTooFar
         40   27 0051BA90 bufio.ErrBufferFull
         41   28 0051BAA0 bufio.ErrFinalToken
         42   29 0051BAB0 bufio.ErrInvalidUnreadByte
         43   2A 0051BAC0 bufio.ErrInvalidUnreadRune
         44   2B 0051BAD0 bufio.ErrNegativeAdvance
         45   2C 0051BAE0 bufio.ErrNegativeCount
         46   2D 0051BAF0 bufio.ErrTooLong
         47   2E 0051BB00 bufio.errNegativeRead
         48   2F 0051BB10 bufio.errNegativeWrite
         49   30 001E1D40 bufio.init
         50   31 001E19E0 bufio.init.ializers
         51   32 00537820 bufio.initdone
         52   33 0036C7D0 bufio.statictmp_0
         53   34 0036C7E0 bufio.statictmp_1
         54   35 000C6600 bytes.(*Buffer).Len
         55   36 000C7090 bytes.(*Buffer).Read
         56   37 000C71D0 bytes.(*Buffer).ReadByte
         57   38 000C6BB0 bytes.(*Buffer).ReadFrom
         58   39 000C6620 bytes.(*Buffer).Reset
         59   3A 000C6530 bytes.(*Buffer).String
         60   3B 000C7260 bytes.(*Buffer).UnreadByte
         61   3C 000C6950 bytes.(*Buffer).Write
         62   3D 000C6FD0 bytes.(*Buffer).WriteByte
         63   3E 000C6A80 bytes.(*Buffer).WriteString
         64   3F 000C6E60 bytes.(*Buffer).WriteTo
         65   40 000C6640 bytes.(*Buffer).grow
         66   41 000C88B0 bytes.(*Reader).Len
         67   42 000C88E0 bytes.(*Reader).Read
         68   43 000C89E0 bytes.(*Reader).ReadByte
         69   44 000C8A60 bytes.(*Reader).UnreadByte
         70   45 000C8B20 bytes.(*Reader).WriteTo
         71   46 000C7B60 bytes.EqualFold
         72   47 0051BB20 bytes.ErrTooLarge
         73   48 000C7E10 bytes.Index
         74   49 000C7320 bytes.Map
         75   4A 000C8C50 bytes.NewReader
         76   4B 000C7AC0 bytes.TrimRight
         77   4C 000C7670 bytes.TrimRightFunc
         78   4D 0051BB30 bytes.errNegativeRead
         79   4E 000C8850 bytes.hashStr
         80   4F 000C85E0 bytes.indexRabinKarp
         81   50 000C8F70 bytes.init
         82   51 000C8E90 bytes.init.ializers
         83   52 00537821 bytes.initdone
         84   53 000C7790 bytes.lastIndexFunc
         85   54 000C78A0 bytes.makeASCIISet
         86   55 000C78F0 bytes.makeCutsetFunc
         87   56 000C8D70 bytes.makeCutsetFunc.func1
         88   57 000C8DB0 bytes.makeCutsetFunc.func2
         89   58 000C8DE0 bytes.makeCutsetFunc.func3
         90   59 000C6DA0 bytes.makeSlice
         91   5A 000C8CF0 bytes.makeSlice.func1
         92   5B 0036C7F0 bytes.statictmp_2
         93   5C 0036C800 bytes.statictmp_5
         94   5D 001E8DC0 compress/flate.(*CorruptInputError).Error
         95   5E 001E8E90 compress/flate.(*InternalError).Error
         96   5F 001E8B50 compress/flate.(*byFreq).Len
         97   60 001E8BB0 compress/flate.(*byFreq).Less
         98   61 001E8C50 compress/flate.(*byFreq).Swap
         99   62 001E89B0 compress/flate.(*byLiteral).Len
        100   63 001E8A10 compress/flate.(*byLiteral).Less
        101   64 001E8AA0 compress/flate.(*byLiteral).Swap
        102   65 001E6090 compress/flate.(*decompressor).Close
        103   66 001E5E30 compress/flate.(*decompressor).Read
        104   67 001E7DD0 compress/flate.(*decompressor).Reset
        105   68 001E7630 compress/flate.(*decompressor).copyData
        106   69 001E7270 compress/flate.(*decompressor).dataBlock
        107   6A 001E7B10 compress/flate.(*decompressor).huffSym
        108   6B 001E6820 compress/flate.(*decompressor).huffmanBlock

...

       1678  68D 00279090 encoding/json.hex
       1679  68E 00251B80 encoding/json.htmlSafeSet
       1680  68F 000D8C00 encoding/json.init
       1681  690 000D89B0 encoding/json.init.ializers
       1682  691 00537843 encoding/json.initdone
       1683  692 000CDE10 encoding/json.intEncoder
       1684  693 000CEA80 encoding/json.interfaceEncoder
       1685  694 000CD040 encoding/json.invalidValueEncoder
       1686  695 000CC2E0 encoding/json.isEmptyValue
       1687  696 000CB7B0 encoding/json.isValidNumber
       1688  697 000D0820 encoding/json.isValidTag
       1689  698 000D9010 encoding/json.jsonError.Error
       1690  699 000CF250 encoding/json.mapEncoder.encode
       1691  69A 000D92D0 encoding/json.mapEncoder.encode-fm
       1692  69B 000D8760 encoding/json.mapEncoder.encode.func1
       1693  69C 000CD0A0 encoding/json.marshalerEncoder

...

       2084  823 00372C60 go.itab.go.uber.org/zap.errArray,go.uber.org/zap/zapcore.ArrayMarshaler
       2085  824 00372C80 go.itab.go.uber.org/zap.float32s,go.uber.org/zap/zapcore.ArrayMarshaler
       2086  825 00372CA0 go.itab.go.uber.org/zap.float64s,go.uber.org/zap/zapcore.ArrayMarshaler
       2087  826 00372CC0 go.itab.go.uber.org/zap.int16s,go.uber.org/zap/zapcore.ArrayMarshaler
       2088  827 00372CE0 go.itab.go.uber.org/zap.int32s,go.uber.org/zap/zapcore.ArrayMarshaler
       2089  828 00372D00 go.itab.go.uber.org/zap.int64s,go.uber.org/zap/zapcore.ArrayMarshaler
       2090  829 00372D20 go.itab.go.uber.org/zap.int8s,go.uber.org/zap/zapcore.ArrayMarshaler
       2091  82A 00372D40 go.itab.go.uber.org/zap.ints,go.uber.org/zap/zapcore.ArrayMarshaler
       2092  82B 00377280 go.itab.go.uber.org/zap.nopCloserSink,go.uber.org/zap.Sink
       2093  82C 00372D60 go.itab.go.uber.org/zap.optionFunc,go.uber.org/zap.Option

...

       2855  B26 00181CD0 internal/x/crypto/chacha20poly1305.(*chacha20poly1305).Seal
       2856  B27 00182470 internal/x/crypto/chacha20poly1305.(*chacha20poly1305).open
       2857  B28 00182F50 internal/x/crypto/chacha20poly1305.(*chacha20poly1305).openGeneric
       2858  B29 00182100 internal/x/crypto/chacha20poly1305.(*chacha20poly1305).seal
       2859  B2A 001828B0 internal/x/crypto/chacha20poly1305.(*chacha20poly1305).sealGeneric
...

Third-party library functions have also been exported.
Since most of the code for the project is not stored in the main package, it is actually equivalent to all function names being leaked.

It is hoped that only functions that explicitly mark //export will be exported, not all functions will be exported.

@ianlancetaylor ianlancetaylor changed the title “go build -buildmode=c-shared” compiled dll, Goruntime, third-party library functions that should not be exported. cmd/link: -buildmode=c-shared exports many functions, not just //export functions Mar 8, 2019
@ianlancetaylor ianlancetaylor added help wanted OS-Windows NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels Mar 8, 2019
@ianlancetaylor ianlancetaylor added this to the Unplanned milestone Mar 8, 2019
@ianlancetaylor
Copy link
Contributor

CC @nadiasvertex

@AndrusGerman
Copy link

This problem also occurs in Linux.

@nwoodmsft
Copy link

nwoodmsft commented Oct 14, 2020

This seems like a significant issue and quite easy to hit on Windows.

Using go 1.15.2 (but this also reproduces on 1.14 and 1.13) I can hit the error "Error: export ordinal too large" during compilation after importing a few 3rd party packages. My code only intends to export one function, but as this issue describes...dumpbin shows thousands of symbols being exported for each of the 3rd party packages that I imported. This quickly causes me to hit the 'export ordinal too large error'.

Is there any workaround that you are aware of for this? (switching to another buildmode such as -buildmode=exe is not an option for projects which require a shared library to be produced).

@networkimprov
Copy link

networkimprov commented Oct 14, 2020

@gopherbot
Copy link

Change https://golang.org/cl/262797 mentions this issue: cmd/cgo: avoid exporting all symbols on windows buildmode=c-shared

@qmuntal
Copy link
Contributor

qmuntal commented Oct 15, 2020

I´ve submitted a commit which adds __declspec(dllexport) attribute on the C wrappers of exported functions. As per https://sourceware.org/binutils/docs/ld/WIN32.html this will avoid exporting all the unnecessary symbols.

I guess it can also fix #40795 by adding a dummy __declspec(dllexport) function but I´ll try it in another CL.

@nwoodmsft
Copy link

nwoodmsft commented Oct 17, 2020

That is fantastic news - thanks for taking a look at this @qmuntal ! Is there a workaround that we use today with golang 1.13 or 1.14 to avoid the unnecessary symbols being exported? I was trying to see if there is a way to call go build with params that would achieve something like -Wl,--exclude-all-symbols but still export the symbols for the functions we marked in the go code with //export ?

Edit: The following approach worked for me, but i'm still curious if there is a simpler/better way:

go build -buildmode=c-shared -ldflags="-extldflags=-Wl,--version-script=myproject.version" -o bin\myproject.dll myproject/sdk

Where the content of myproject.version file is:

CODEABI_1.0 {
    global: MyExportedFunction;MyOtherExportedFunction;
    local: *;
};

Resultant DLL only exports the functions I requested in the global section of the myproject.version file (and the syntax of that file also supports wildcard * to make it easy to export a bunch of functions without having to explicitly name each one).

@networkimprov
Copy link

@gopherbot please backport to 1.15

buildmode=pie became the default in 1.15, so folks have to manually set buildmode=exe to work around this bug.

@gopherbot
Copy link

Backport issue(s) opened: #43591 (for 1.15).

Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://golang.org/wiki/MinorReleases.

@dmitshur dmitshur added NeedsFix The path to resolution is known, but the work has not been done. and removed NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels Feb 12, 2021
@dmitshur dmitshur modified the milestones: Unplanned, Go1.16 Feb 12, 2021
@gopherbot
Copy link

Change https://golang.org/cl/300693 mentions this issue: [release-branch.go1.15] cmd/cgo: avoid exporting all symbols on windows buildmode=c-shared

gopherbot pushed a commit that referenced this issue Mar 31, 2021
…ws buildmode=c-shared

Disable default symbol auto-export behaviour by marking exported
function with the __declspec(dllexport) attribute. Old behaviour can
still be used by setting -extldflags=-Wl,--export-all-symbols.

See https://sourceware.org/binutils/docs/ld/WIN32.html for more info.

This change cuts 50kb of a "hello world" dll.

Updates #6853.
Updates #30674.
Fixes #43591.

Change-Id: I9c7fb09c677cc760f24d0f7d199740ae73981413
Reviewed-on: https://go-review.googlesource.com/c/go/+/262797
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/300693
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: David Chase <drchase@google.com>
@golang golang locked and limited conversation to collaborators Mar 31, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge help wanted NeedsFix The path to resolution is known, but the work has not been done. OS-Windows
Projects
None yet
Development

No branches or pull requests

8 participants