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

cmd/pack: gc linkobjs not recognized in 1.16b1 #43271

Closed
benjaminp opened this issue Dec 18, 2020 · 11 comments
Closed

cmd/pack: gc linkobjs not recognized in 1.16b1 #43271

benjaminp opened this issue Dec 18, 2020 · 11 comments
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. release-blocker
Milestone

Comments

@benjaminp
Copy link
Contributor

$ cat test.sh
#!/bin/bash
echo "package main" > main.go
echo "func main() {}" >> main.go
$GO tool compile -p main -complete -linkobj  pkg.a -o pkg-i.a main.go
$GO tool pack c link.a pkg.a
echo "packed contents:"
$GO tool pack tv link.a
echo "unpacked member head:"
$GO tool pack x link.a
head -n1 pkg.a
$ GO=go1.16b1/bin/go ./test.sh 
packed contents:
-rw-rw-r--      0/0              1258 Dec 31 18:00 1969 pkg.a
unpacked member head:
!<arch>
$ GO=go1.15.6/bin/go ./test.sh 
packed contents:
-rw-r--r--      0/0               852 Dec 31 18:00 1969 pkg.a
unpacked member head
go object linux amd64 go1.15.6 X:framepointer
@ianlancetaylor
Copy link
Contributor

CC @thanm @jeremyfaller @cherrymui

@ianlancetaylor ianlancetaylor added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Dec 18, 2020
@ianlancetaylor ianlancetaylor added this to the Go1.16 milestone Dec 19, 2020
@ianlancetaylor
Copy link
Contributor

Marking as a release blocker to make sure we figure out what is going on.

@cherrymui
Copy link
Member

cherrymui commented Dec 19, 2020

Sorry, I'm not sure I understand what you wanted to do here.

pkg.a is already an archive file. You pack it again to link.a, then unpack it, but you are not expecting to get pkg.a back. Why do you want to pack an already-packed archive file?

@benjaminp
Copy link
Contributor Author

This situation arises when creating a package archive containing gc output and native object files. go simply appends native objects to the archive that gc emits using its knowledge of the archive format. Historically (since CL 102236), one could achieve the same end with cmd/pack because pack "saw through" gc output archives.

(I'm not at all wedded to using cmd/pack. If there was some way to pass native object files to the final link command, less copying would have to happen.)

@cherrymui
Copy link
Member

I think you can use go tool pack r to append native objects to Go archive file, instead of go tool pack c.

If there was some way to pass native object files to the final link command, less copying would have to happen.

If you use go build, if you put a native object file named .syso in the same directory as Go source files in a package, when building the package the go command will pack it automatically. See the runtime/race package as an example.

@benjaminp
Copy link
Contributor Author

I think you can use go tool pack r to append native objects to Go archive file, instead of go tool pack c.

c is a bit more convenient for me because I'm making a separate file from the gc output and used to work fine.

If there was some way to pass native object files to the final link command, less copying would have to happen.

If you use go build, if you put a native object file named .syso in the same directory as Go source files in a package, when building the package the go command will pack it automatically. See the runtime/race package as an example.

I just meant it would be nicer from a scalability perspective to not have to duplicate native objects into an archive in order to pass them to link. (I.e., the same reason thin archives and later gold/lld's --start-lib & --end-lib exist.)

@gopherbot
Copy link

Change https://golang.org/cl/279483 mentions this issue: cmd/pack: treat compiler's -linkobj output as "compiler object"

@cherrymui
Copy link
Member

The CL above restores the Go 1.15 behavior.

But I wanted to mention that this behavior is somewhat accidental. With Go 1.15's cmd/pack, isGoCompilerObjFile is supposed to return true when the input has exactly two entries __.PKGDEF and _go_.o. This is what I did when I rewrote cmd/pack in Go 1.16. However, when the input has one single entry _go_.o, it actually returns true. When name is _go_.o, the first iteration of the inner loop at https://go.googlesource.com/go/+/refs/tags/go1.15.6/src/cmd/pack/pack.go#537 will simply skip match[0] and the second iteration returns true. Looking at the code it doesn't seem to be intended.

If you want the append semantics, I would recommend using the "r" command, instead of this peculiar undocumented "see through" behavior of the "c" command.

@benjaminp
Copy link
Contributor Author

The CL above restores the Go 1.15 behavior.

Thank you.

But I wanted to mention that this behavior is somewhat accidental. With Go 1.15's cmd/pack, isGoCompilerObjFile is supposed to return true when the input has exactly two entries __.PKGDEF and _go_.o. This is what I did when I rewrote cmd/pack in Go 1.16. However, when the input has one single entry _go_.o, it actually returns true. When name is _go_.o, the first iteration of the inner loop at https://go.googlesource.com/go/+/refs/tags/go1.15.6/src/cmd/pack/pack.go#537 will simply skip match[0] and the second iteration returns true. Looking at the code it doesn't seem to be intended.

If you want the append semantics, I would recommend using the "r" command, instead of this peculiar undocumented "see through" behavior of the "c" command.

I thought the commit message of CL 102236 meant the behavior was not accidental. Before the compiler always emitted an archive, one could use pack c to put compiler output into an archive. The intention of the CL was to preserve that behavior after archives became the only output format.

@cherrymui
Copy link
Member

Before the compiler always emitted an archive, one could use pack c to put compiler output into an archive. The intention of the CL was to preserve that behavior after archives became the only output format.

It is not guaranteed that the tool's (e.g. pack) behavior not change, especially undocumented behavior. Use the "r" command if you want to append.

@mdempsky
Copy link
Member

mdempsky commented Dec 22, 2020

With Go 1.15's cmd/pack, isGoCompilerObjFile is supposed to return true when the input has exactly two entries __.PKGDEF and _go_.o.

The comment certainly says that. But judging by the nested for loops, I think I did specifically intend for it to match archive files that contained (1) only __.PKGDEF, (2) only _go_.o, or (3) only __.PKGDEF and _go_.o in that order. (Though I notice now that it also matches empty archive files, which I think was not intended.)

I think if it was really my intention to require that both files were present, I would have used a single for loop.

@golang golang locked and limited conversation to collaborators Dec 22, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. release-blocker
Projects
None yet
Development

No branches or pull requests

5 participants