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"
...
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/amd64What environment are you running Garble on?
go envOutputWhat did you do?
Given a basic http server,
What did you expect to see?
The program when compiled with go works fine.
What did you see instead?
Replacing this with output from
garble reversegives: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.
the garble build debug output has a line that seems to indicate this: