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

garble 32-bit arm builds panic: unaligned 64-bit atomic operation #686

Closed
argon-18-elem opened this issue Feb 24, 2023 · 1 comment · Fixed by #702
Closed

garble 32-bit arm builds panic: unaligned 64-bit atomic operation #686

argon-18-elem opened this issue Feb 24, 2023 · 1 comment · Fixed by #702

Comments

@argon-18-elem
Copy link

What version of Garble and Go are you using?

$ garble version
mvdan.cc/garble v0.9.2
Build settings:
      -buildmode exe
       -compiler gc
     CGO_ENABLED 1
          GOARCH amd64
            GOOS linux
         GOAMD64 v1

$ go version
go version go1.20 linux/amd64

What environment are you running Garble on?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/user/.cache/go-build"
GOENV="/home/user/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/user/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/user/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.20"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/user/repos/work/project/go.mod"
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build1229348132=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Given a basic http server,

package main

import (
	"log"
	"net/http"
)

func main() {
	log.Println("Starting HTTP Server.")
	m := http.NewServeMux()
	srv := http.Server{
		Addr:    ":8080",
		Handler: m,
	}
	m.HandleFunc("/", rootHandler)

	srv.ListenAndServe()
}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("OK\n"))
}

What did you expect to see?

The program when compiled with go works fine.

$ GOARCH=arm GOOS=linux go build .
$ ./GarbleHttp &
2023/02/24 16:57:53 Starting HTTP Server.

$ curl localhost:8080
OK
$ 

What did you see instead?

$ GOARCH=arm GOOS=linux garble build .
$ ./GarbleHttp &
2023/02/24 16:57:53 Starting HTTP Server.

$ curl localhost:8080
panic: unaligned 64-bit atomic operation

goroutine 1 [running]:
runtime/internal/atomic.panicUnaligned()
        runtime/internal/atomic/unaligned.go:8 +0x24
runtime/internal/atomic.Store64(0x92c1cc, 0x63f9338100)
        runtime/internal/atomic/XiKmtDXVGAk.s:291 +0x14
sync/atomic.(*ZQwlhRyn1YC9).Store(...)
        ZD2OCzn.go:1
lYKjcj_Hxvl.(*t14t6G35ZFlV).dvpkxnMNk(0x92c190, {0x2f2818, 0x9160f0}, 0x0, 0x1)
        zOyAdFVZPOv.go:1 +0x120
lYKjcj_Hxvl.(*Pl7xm3).Serve(0x966000, {0x2f2004, 0x91e110})
        vjKlsfhFUnbj.go:1 +0x468
lYKjcj_Hxvl.(*Pl7xm3).ListenAndServe(0x966000)
        Xec7sv5.go:1 +0xa4
main.main()
        uvg12bqU.go:1 +0x12c
curl: (56) Recv failure: Connection reset by peer
[1]+  Exit 2                  ./GarbleHttp

Replacing this with output from garble reverse gives:

panic: unaligned 64-bit atomic operation

goroutine 1 [running]:
runtime/internal/atomic.panicUnaligned()
        runtime/internal/atomic/unaligned.go:8 +0x24
runtime/internal/atomic.Store64(0x86e1cc, 0x63f9342800)
        runtime/internal/atomic/XiKmtDXVGAk.s:291 +0x14
sync/atomic.(*Uint64).Store(...)
        sync/atomic/type.go:148
net/http.(*conn).setState(0x86e190, {0x2f2818, 0x80e118}, 0x0, 0x1)
        net/http/server.go:1794 +0x120
net/http.(*Server).Serve(0x922000, {0x2f2004, 0x80c130})
        net/http/server.go:3088 +0x468
net/http.(*Server).ListenAndServe(0x922000)
        net/http/server.go:2988 +0xa4
main.main()
        GarbleHttp/main.go:17 +0x12c

It appears that building using garble is somehow breaking the alignment of 64 bit types when running on 32 bit architecture.

Cause Speculation

It seems that in go/src/atomic/type.go, maybe the Uint64 struct is losing its alignment instruction due to garble.

type Uint64 struct {
	_ noCopy
	_ align64
	v uint64
}

the garble build debug output has a line that seems to indicate this:

...
[garble] type "align64" hashed with 6f52ca17… to "d1XMq5iQRpd"
[garble] field "v" hashed with struct fields to "yW3TYC_v"
[garble] type "Uint32" hashed with 6f52ca17… to "MeO4NGyh"
[garble] type "Uint64" hashed with 6f52ca17… to "ZQwlhRyn1YC9"
...
@MrBruz
Copy link

MrBruz commented Mar 3, 2023

Same issue here

mvdan added a commit to mvdan/garble-fork that referenced this issue Mar 11, 2023
Added in Go 1.19, types like sync/atomic.Uint64 are handy,
because they ensure proper alignment even on 32-bit GOOSes.
However, this was done via a magic `type align64 struct{}`,
which the compiler spotted by name.

To keep that magic working, do not obfuscate the name.
Neither package path was being obfuscated,
as both packages contain compiler intrinsics already.

Fixes burrowers#686.
mvdan added a commit to mvdan/garble-fork that referenced this issue Mar 11, 2023
Added in Go 1.19, types like sync/atomic.Uint64 are handy,
because they ensure proper alignment even on 32-bit GOOSes.
However, this was done via a magic `type align64 struct{}`,
which the compiler spotted by name.

To keep that magic working, do not obfuscate the name.
Neither package path was being obfuscated,
as both packages contain compiler intrinsics already.

Fixes burrowers#686.
mvdan added a commit that referenced this issue Mar 11, 2023
Added in Go 1.19, types like sync/atomic.Uint64 are handy,
because they ensure proper alignment even on 32-bit GOOSes.
However, this was done via a magic `type align64 struct{}`,
which the compiler spotted by name.

To keep that magic working, do not obfuscate the name.
Neither package path was being obfuscated,
as both packages contain compiler intrinsics already.

Fixes #686.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

2 participants