Skip to content

cmd/link: fails to link package having a .syso file when using external linker #33139

Closed
@jpap

Description

@jpap

Being able to inclue a .syso file in a package is great. A Go program using that package works well when that program is linked using the internal linker. Link is however broken when the that program is linked using the external linker, for example, because the Go program also uses cgo.

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

$ go version
go version go1.12.7 linux/amd64

Does this issue reproduce with the latest release?

This affects all go versions, including tip (at the time of submission).

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

This affects all GOOS/GOARCH pairs. I have tried it on darwin/amd64 and linux/amd64.

go env Output
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/jpap/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/jpap/go"
GOPROXY=""
GORACE=""
GOROOT="/home/jpap/Local/go"
GOTMPDIR=""
GOTOOLDIR="/home/jpap/Local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
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-build378647343=/tmp/go-build -gno-record-gcc-switches"

What did you do?

  1. Create a package that has a .syso file.
  2. Create a main package that uses the package above.
  3. Link the main package in external link mode to build an executable. (This could be explicit, using -ldflags='-linkmode=external', or by using cgo in the main package, where the external linker is then required.)

Sample project follows...

Directory structure

$GOPATH/src/jpap.org/linktest
├── cmd
│   ├── external
│   │   └── main.go
│   └── internal
│       └── main.go
└── syso
    ├── asm
    │   ├── Makefile
    │   ├── test_darwin.s
    │   └── test_linux.s
    ├── test.go
    ├── test.s
    └── test.syso

To build the test.syso file on Linux using gcc,

$ cd $GOPATH/src/jpap.org/linktest/syso/asm
$ make linux
gcc -c -o ../test.syso test_linux.s
$

syso/asm/Makefile

linux:
	gcc -c -o ../test.syso test_linux.s
darwin:
	gcc -c -o ../test.syso test_darwin.s

syso/asm/test_darwin.s

	.globl _asmTest
_asmTest:
	ret

syso/asm/test_linux.s

	.globl asmTest
asmTest:
	ret

syso/test.go

package syso

func Test()

syso/test.s

#include "textflag.h"

TEXT ·Test(SB), NOSPLIT, $0
	JMP asmTest(SB)

cmd/internal/main.go

package main

import (
	"jpap.org/linktest/syso"
)

func main() {
	syso.Test()
}

cmd/external/main.go


/*
 // Force use of external linker
 #include <stdio.h>
 */
import "C"

import (
	"jpap.org/linktest/syso"
)

func main() {
	syso.Test()
}

What did you expect to see?

  1. Link successful, and executable built for both cmd/internal/main.go (using internal link) and cmd/external/main.go (using external link).

What did you see instead?

  1. Internal link succeeds for cmd/internal/main.go.
  2. External link fails for cmd/external/main.go with error relocation target XXX not defined for each referenced global symbol in the imported package .syso, for example:
$ cd $GOPATH/src/jpap.org/cmd/external
$ go build .
# jpap.org/linktest/cmd/external
jpap.org/linktest/syso.Test: relocation target asmTest not defined
$ 

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions