Hacker News new | ask | show | jobs
by Beltalowda 1330 days ago
In Go you can use "go version -m my-go-binary" and get a list of dependencies and other build information. For example (may wrap a bit ugly on HN):

  [~]% go version -m =godoc
  /home/belta/bin/godoc: go1.18.3
          path    golang.org/x/tools/cmd/godoc
          mod     golang.org/x/tools      v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
          dep     github.com/yuin/goldmark        v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
          dep     golang.org/x/mod        v0.6.0-dev.0.20220419223038-86c51ed26bb4        h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
          dep     golang.org/x/net        v0.0.0-20220722155237-a158d28d115b      h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
          dep     golang.org/x/sys        v0.0.0-20220722155257-8c9f86f7a55f      h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
          build   -compiler=gc
          build   CGO_ENABLED=0
          build   GOARCH=amd64
          build   GOOS=linux
          build   GOAMD64=v1
So scanning your binaries, if you want, is fairly easy.

Other than that, this is the "Great Static vs. Dynamic Linking Debate", which has been done quite a few times. I have little desire to repeat it, but both approaches have their advantages and downsides, and with good tooling (like the above) I think many downsides of static linking can be managed quite well.

2 comments

That's a great solution, actually. I'm not familiar with go, but I thought it compiled to native code and did not require a virtual machine at runtime. So is this metadata enforced/inserted by the compiler into the binary, or does it require specific build tooling that may or may not be available on end-user systems?
The compiler adds it in the .go.buildinfo section; something like "objdump -sj .go.buildinfo" should also display it, kind of, but it needs a bit more parsing to display well. You need some tooling, but it's not horribly complex, and I think some kind of tooling would be unavoidable anyway.

I think there's a lot of potential for better tooling here in the form of language support, package manager support, etc.

Unfortunately that shows the Go libraries involved, but not the C libraries those Go libraries depend on (right?). So that might tell me that a Go program includes 'crypto', but not whether or not that 'crypto' linked in OpenSSL 1.1.1 or OpenSSL 3.x.

So the static linking dependency analysis problem remains.

cgo stuff gets dynamically linked by default, although you can link it statically (usually); the OpenSSL bindings for Go seem to support it, but almost no one uses these[1].

You're right that these don't show up, but in practice it's mostly a non-issue for the most part as cgo isn't used that often and purely statically linked cgo even less so, and when it is it's often in the form of e.g. go-sqlite3 where the SQLite version is tied to the module version.

The problem is that "static linking" means "grab whatever is in /usr/lib/libfoo.a, whatever that may be". I'm not sure if there is a good way to solve this in a generic way that works everywhere, outside of keeping track of sums.

[1]: https://pkg.go.dev/github.com/spacemonkeygo/openssl?tab=impo...