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: add a flag to the linker to do not write function names to runtime.pclntab #36555

Open
xaionaro opened this issue Jan 14, 2020 · 9 comments
Milestone

Comments

@xaionaro
Copy link

@xaionaro xaionaro commented Jan 14, 2020

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

go version
go version devel +71154e061f Tue Jan 14 17:13:34 2020 +0000 linux/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
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/experiment0/.cache/go-build"
GOENV="/home/experiment0/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/experiment0/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/experiment0/.gimme/versions/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/experiment0/.gimme/versions/go/pkg/tool/linux_amd64"
GCCGO="/usr/bin/gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build891839909=/tmp/go-build -gno-record-gcc-switches"

What did you do?

go get github.com/u-root/u-root
u-root -o /dev/null -build bb core boot
go get github.com/u-root/u-root/bb
go tool nm -size -sort size "$(go env GOPATH)"/bin/bb | head -1

What did you expect to see?

  e02ba0    3836272 r runtime.pclntab

What did you see instead?

  e39500    4808314 r runtime.pclntab

Proposal

I found here https://groups.google.com/d/msg/golang-nuts/hEdGYnqokZc/zQojaoWlAgAJ that a binary size could be reduced by avoiding of wasting space on function names within runtime.pclntab. So I propose to add a linker flag (for example -stripfnnames) to do that. We need such feature for applying Golang into embedded environments (with very limited total space).

I would like to prepare a PR if it will be approved.

@networkimprov

This comment has been minimized.

Copy link

@networkimprov networkimprov commented Jan 14, 2020

See #36313

@xaionaro

This comment has been minimized.

Copy link
Author

@xaionaro xaionaro commented Jan 14, 2020

@networkimprov : thank you. However I saw that ticket. It contains discussion how to reduce runtime.pclntab for a generic case. While my proposal is about a special case (embedded systems), so I created a new ticket :)


UPD: Wrote a comment to #36313 with a proposal to add an option to select a simple GC which does not require so complex runtime.pclntab. If the proposal will be approved then this ticket is indeed not actual.

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Jan 14, 2020

Removing function names from runtime.pclntab would break programs that use runtime.Callers, which is a lot of programs. For example, the testing and log packages would partially break.

@xaionaro

This comment has been minimized.

Copy link
Author

@xaionaro xaionaro commented Jan 14, 2020

Removing function names from runtime.pclntab would break programs that use runtime.Callers, which is a lot of programs. For example, the testing and log packages would partially break.

@ianlancetaylor :

  1. It's only for embedded (where it's extremely important to reduce the size, and people are ready to sacrifice with log/testing for that). Moreover we can add a build-tag for -stripfnnames and use it to remove functions which uses runtime.Callers or to change their behavior. In my opinion it would good enough to just change the behavior to print <unknown> instead of function names.
  2. If I understand correctly testing and log will actually continue to work even without modifications (but I did not look into to this part of the code, yet). They will just print emptiness instead of function names.
@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Jan 14, 2020

I believe the testing.(*T).Helper function, for example, will break.

This will also likely break profiling information.

I understand that you would find it useful but I'm reluctant to endorse a change that will break code in ways that people will not know how to expect. I would rather find other ways to reduce binary size.

@xaionaro

This comment has been minimized.

Copy link
Author

@xaionaro xaionaro commented Jan 14, 2020

that will break code in ways that people will not know how to expect.

We can forbid using broken functions via the build-tag (added automatically by -stripfnnames).

@networkimprov

This comment has been minimized.

Copy link

@networkimprov networkimprov commented Jan 14, 2020

Ian may be concerned that you'll eventually realize that Go isn't the best choice for an embedded app, and switch to Rust or http://ziglang.org ;-)

@beoran

This comment has been minimized.

Copy link

@beoran beoran commented Jan 15, 2020

For embedded Go, where size is really important, for the time being, https://tinygo.org/ is the better solution.

Rather than having a specific build flag for stripping runtime.pclntab, I think that in the long run, what we need is new GOOS, such as "none" for running on raw iron, and "linux-embedded" for running an on embedded linux OS should be added. The "none" variants then allow building an OS kernel, and the -embedded variants then do a few things differently to save on space.

@xaionaro

This comment has been minimized.

Copy link
Author

@xaionaro xaionaro commented Jan 15, 2020

For embedded Go, where size is really important, for the time being, https://tinygo.org/ is the better solution.

I tried tinygo few times for u-root. And tinygo is a nice and interesting project, but it appears it has invalid CGo parser (which has problems with #define and other stuff), (if I remember correctly) does not support Golang's assembly language, it does not implement too much stuff from standard packages (which it overrides) and it even does not support something related to func() variables so it panics while compilation of u-root/bb. I've spent some time and realized that it's would require too much time to port the project to tinygo. Also tinygo's README.md says:

Non-goals: ...; Be able to compile every Go program out there.


Ian may be concerned that you'll eventually realize that Go isn't the best choice for an embedded app, and switch to Rust or http://ziglang.org ;-)

I believe the community of Golang is wise and will be able to find a solution for cases like mine :)
And I will be glad to somehow help to implement an approved solution when there will be one.

Anyway it would take much more time to port project to Rust than even to port it to tinygo :)

@cagedmantis cagedmantis added this to the Backlog milestone Jan 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.