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

runtime: building with -gcflags="-N -l" fails #18774

Closed
artiomn opened this issue Jan 24, 2017 · 14 comments

Comments

Projects
None yet
5 participants
@artiomn
Copy link

commented Jan 24, 2017

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

1.6.2 on Linux, 1.7 windows/amd64 on windows.

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

Windows x86_64, Linux x86_64, MacOS x86_64.

What did you do?

I had built go package and have got stack overflow in the go compiler (with a specific parameters combination). Problem is reproduced on all operating systems, described above.

user@dev-debian ~/Desktop/repos/go_packages/src/test $ uname -a                     
Linux dev-debian 3.16.0-4-amd64 #1 SMP Debian 3.16.36-1+deb8u2 (2016-10-19) x86_64 GNU/Linux
user@dev-debian ~/Desktop/repos/go_packages/src/test $ cat main.go
go
package main

import "fmt"


func main() {
    fmt.Println("hello world")
}
user@dev-debian ~/Desktop/repos/go_packages/src/test $ echo "$GOOS, $GOARCH"                      
linux, amd64
user@dev-debian ~/Desktop/repos/go_packages/src/test $ ls
main.go
user@dev-debian ~/Desktop/repos/go_packages/src/test $ go build -gcflags="-N -l" -pkgdir pkg -o test .
# test
runtime.typedslicecopy: nosplit stack overflow
        584     assumed on entry to runtime.typedslicecopy (nosplit)
        448     after runtime.typedslicecopy (nosplit) uses 136
        440     on entry to runtime.cgoCheckSliceCopy (nosplit)
        376     after runtime.cgoCheckSliceCopy (nosplit) uses 64
        368     on entry to runtime.cgoCheckTypedBlock (nosplit)
        168     after runtime.cgoCheckTypedBlock (nosplit) uses 200
        160     on entry to runtime.cgoCheckBits (nosplit)
        24      after runtime.cgoCheckBits (nosplit) uses 136
        16      on entry to runtime.cgoIsGoPointer (nosplit)
        -32     after runtime.cgoIsGoPointer (nosplit) uses 48
runtime.sigtrampgo: nosplit stack overflow
        584     assumed on entry to runtime.sigtrampgo (nosplit)
        392     after runtime.sigtrampgo (nosplit) uses 192
        384     on entry to runtime.sigfwdgo (nosplit)
        288     after runtime.sigfwdgo (nosplit) uses 96
        280     on entry to runtime.dieFromSignal (nosplit)
        240     after runtime.dieFromSignal (nosplit) uses 40
        232     on entry to runtime.setsig (nosplit)
        40      after runtime.setsig (nosplit) uses 192
        32      on entry to runtime.funcPC (nosplit)
        0       after runtime.funcPC (nosplit) uses 32
        -8      on entry to runtime.add (nosplit)
runtime.cgocallback_gofunc: nosplit stack overflow
        584     assumed on entry to runtime.cgocallback_gofunc (nosplit)
        576     after runtime.cgocallback_gofunc (nosplit) uses 8
        568     on entry to runtime.cgocallbackg (nosplit)
        480     after runtime.cgocallbackg (nosplit) uses 88
        472     on entry to runtime.exitsyscall (nosplit)
        352     after runtime.exitsyscall (nosplit) uses 120
        344     on entry to runtime.exitsyscallfast (nosplit)
        184     after runtime.exitsyscallfast (nosplit) uses 160
        176     on entry to runtime.writebarrierptr (nosplit)
        128     after runtime.writebarrierptr (nosplit) uses 48
        120     on entry to runtime.cgoCheckWriteBarrier (nosplit)
        56      after runtime.cgoCheckWriteBarrier (nosplit) uses 64
        48      on entry to runtime.cgoIsGoPointer (nosplit)
        0       after runtime.cgoIsGoPointer (nosplit) uses 48
        -8      on entry to runtime.cgoInRange (nosplit)

What did you expect to see?

Compiled binary.

Remarks

Look at the pkgdir parameter, gcflags -N option and GOOS/GOARCH environment variables.
Under Windows it was reproduced even without -pkgdir.

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Jan 24, 2017

Dup of #14319, although that issue has gotten rather complicated.

@ianlancetaylor ianlancetaylor changed the title Stack overflow in the compiler runtime: building with -gcflags="-N -l" fails Jan 24, 2017

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Jan 24, 2017

Note that this is not a stack overflow in the compiler. It is the compiler reporting that the runtime does not guarantee enough stack space for this code to succeed.

@artiomn

This comment has been minimized.

Copy link
Author

commented Jan 24, 2017

runtime.typedslicecopy: nosplit stack overflow

It's a very unclear message, if situation is not a stack overflow.

runtime does not guarantee enough stack space for this code to succeed

Runtime can't allocate enough stack space? Is it not a stack overflow?

@artiomn

This comment has been minimized.

Copy link
Author

commented Jan 24, 2017

How to tune runtime parameters to fix it?

@dr2chase

This comment has been minimized.

Copy link
Contributor

commented Jan 24, 2017

Try nudging 880 up to 912 on these three lines:

src/cmd/internal/obj/stack.go:  StackGuard  = 880*stackGuardMultiplier + StackSystem
src/runtime/stack.go:   _StackGuard = 880*sys.StackGuardMultiplier + _StackSystem
test/nosplit.go:                                        size += (880 - 128) - 128
test/nosplit.go:                                                        size += 880

This may cause other problems, and I am surprised it got as large as 880.
I was working on this CL https://go-review.googlesource.com/c/27511/ to reduce that number back when it was 720.

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Jan 24, 2017

It is not a stack overflow in the compiler. It is the compiler reporting that when you try to run your program it may get a stack overflow at runtime.

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Jan 24, 2017

I note that you may not care about compiling the runtime package itself with -N -l. If you first go install -pkgdir pkg runtime you will get the runtime package built normally. You should then be able to build the rest of your program with -N -l.

@artiomn

This comment has been minimized.

Copy link
Author

commented Jan 24, 2017

It is the compiler reporting that when you try to run your program it may get a stack overflow at runtime.

Is it a stack checker, like address sanitizer, yes?

If you first go install -pkgdir pkg runtime you will get the runtime package built normally.

Ok, thank you.

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Jan 24, 2017

Comparing this to address sanitizer is somewhat misleading. Go stacks have unlimited size. This is implemented by a small prologue at each function which checks whether there is enough stack space available to run the function. If there is not, the entire stack is copied to a larger stack, and then the function continues.

Implementing this requires some functions that do not copy the stack: functions that implement stack coying, that handle signals, that implement cgo calls. Those functions are in the runtime package. The test for whether there is enough stack space available to run a function ensures that there is a small amount of stack space always available to run those runtime functions if necessary. When you compile with -N -l the compiler (really, the linker) is reporting that there are possible call stacks in the runtime package that may require more stack space than is guaranteed to be available. This only happens with -N -l because less optimization means that the functions need more stack space.

@artiomn

This comment has been minimized.

Copy link
Author

commented Jan 24, 2017

Thanks. It's interesting. It's not a sanitizer, really, but more similar to stack guards.
It's a pity, that a specific functions (or code blocks in separated files) can't be built with specific parameters, provided (or removed from the common parameters set) in the blocks.

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Jan 24, 2017

What actual problem are you trying to solve?

@artiomn

This comment has been minimized.

Copy link
Author

commented Jan 24, 2017

I crossbuild people's go code with my own buildsystem, which executes go get/go build, and I need to implement debug mode for people, who want to debug under Linux/macos (and, maybe windows).
Building specific libraries (even go runtime) is possible, but not very convenient for me.
Disabling this options absolutely in typedslicecopy, sigtrampgo and cgocallback_gofunc (i.e., using "magic comment") could be a very good solution.

@bradfitz

This comment has been minimized.

Copy link
Member

commented Mar 21, 2017

@bradfitz

This comment has been minimized.

Copy link
Member

commented Mar 21, 2017

Actually, closing in favor of #14319

@bradfitz bradfitz closed this Mar 21, 2017

@golang golang locked and limited conversation to collaborators Mar 21, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.