Skip to content

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

@argon-18-elem

Description

@argon-18-elem

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"
...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions