Find out which runtime was used to build a Go binary

2,280 views
Skip to first unread message

Ralph Caraveo

unread,
Dec 4, 2015, 6:22:14 PM12/4/15
to golang-nuts
Hi Gophers,

Is there some sort of reliable way to find out the Go runtime that was used to build an arbitrary binary?

So if I have a simple binary (any binary big or small), is there a way to inspect its headers or somehow get at the version of Go used that built the binary?

I know this might be a strange request but any help is appreciated.

Thanks in advance,

@deckarep

Caleb Spare

unread,
Dec 4, 2015, 6:26:15 PM12/4/15
to Ralph Caraveo, golang-nuts
You can try to find the version string in your binary.

$ strings /path/to/binary | grep 'go1\.'
go1.5.2

I'm not sure how reliable this is.

-Caleb
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Ralph Caraveo

unread,
Dec 4, 2015, 6:39:13 PM12/4/15
to golang-nuts, deck...@gmail.com
Ah yes thank you Caleb,

Interestingly for me that works for binaries built with say 1.5 but for this particular binary I have the version doesn't seem to be present in the list of strings output to the screen.

Thanks for this...if anyone has other methods I would be much obliged.

@deckarep

Dave Cheney

unread,
Dec 4, 2015, 6:55:41 PM12/4/15
to golang-nuts, deck...@gmail.com
Maybe it was built from source ?

% strings $(which go) | grep devel

devel +c2290fe Fri Dec 4 23:38:27 2015 +0000

Ralph Caraveo

unread,
Dec 4, 2015, 6:59:33 PM12/4/15
to Dave Cheney, golang-nuts
Thanks Dave,

That's a great point but also looks not to be the case.

Thank You.

@deckarep

Dave Cheney

unread,
Dec 5, 2015, 8:10:44 PM12/5/15
to kei...@alum.mit.edu, golang-nuts
Nice trick Keith. How quickly I have forgotten that gdb exists.

On Sun, Dec 6, 2015 at 11:06 AM, <kei...@alum.mit.edu> wrote:
> The official way to get the version at runtime is runtime.Version. It reads
> from the variable runtime.buildVersion. If you're lucky enough that that
> variable was not dead-code eliminated, you can do:
>
> package main
>
> import "runtime"
>
> func main() {
> println(runtime.Version())
> }
>
>> go build version.go
>> ./version
> devel +8e496f1 Thu Nov 5 15:41:05 2015 +0000
>> gdb version
> (gdb) print 'runtime.buildVersion'
> $1 = 0x47e3c0 "devel +8e496f1 Thu Nov 5 15:41:05 2015 +0000"
>
> That should be more robust than using strings. If strings doesn't return
> something with 'devel' or 'go1.' in it, though, you're probably out of luck.
> runtime.buildVersion has almost certainly been dead-code eliminated.
>
> Maybe we should always keep this variable live? Wouldn't be hard to do,
> I'll add an issue to make this happen for 1.7.

minux

unread,
Dec 5, 2015, 8:56:58 PM12/5/15
to Ralph Caraveo, golang-nuts
On Fri, Dec 4, 2015 at 6:14 PM, Ralph Caraveo <deck...@gmail.com> wrote:
Is there some sort of reliable way to find out the Go runtime that was used to build an arbitrary binary?

So if I have a simple binary (any binary big or small), is there a way to inspect its headers or somehow get at the version of Go used that built the binary?

I know this might be a strange request but any help is appreciated.

Starting from binaries built by Go 1.4, we already embed such information
into binary. The symbol is called 'runtime.buildVersion'.

$ gdb binary
(gdb) p 'runtime.buildVersion'

Note that it's a static variable, so you don't need to run the binary to read
it.

Go 1.5 introduced internal packages to the runtime, so now it's called
'runtime/internal/sys.BuildVersion', but I proposed that we move it back
to 'runtime.buildVersion' for compatibility with older versions.

kei...@alum.mit.edu

unread,
Dec 5, 2015, 9:20:02 PM12/5/15
to golang-nuts, da...@cheney.net
The official way to get the version at runtime is runtime.Version.  It reads from the variable runtime.buildVersion.  If you're lucky enough that that variable was not dead-code eliminated, you can do:

package main

import "runtime"

func main() {
println(runtime.Version())
}

> go build version.go
> ./version
devel +8e496f1 Thu Nov 5 15:41:05 2015 +0000
> gdb version
(gdb) print 'runtime.buildVersion'
$1 = 0x47e3c0 "devel +8e496f1 Thu Nov 5 15:41:05 2015 +0000"

That should be more robust than using strings.  If strings doesn't return something with 'devel' or 'go1.' in it, though, you're probably out of luck.  runtime.buildVersion has almost certainly been dead-code eliminated.

Maybe we should always keep this variable live?  Wouldn't be hard to do, I'll add an issue to make this happen for 1.7.

On Friday, December 4, 2015 at 3:59:33 PM UTC-8, Ralph Caraveo wrote:
Reply all
Reply to author
Forward
0 new messages