Compilers and linkers put their own version information in ELF binaries; we can inspect
with readelf
on the .comment
section, to wit:
$ readelf -p .comment -p .note.gnu.gold-version $(which ja)
String dump of section '.comment':
[ 1] GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
[ 2c] GHC 9.8.2
[ 36] GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
[ 61] rustc version 1.76.0 (07dca489a 2024-02-04)
[ 8d] GCC: (Ubuntu 12.3.0-1ubuntu1~22.04) 12.3.0
String dump of section '.note.gnu.gold-version':
[ c] GNU
[ 10] gold 1.16
This is a bit loud. Let us structure output using Jacinda.
We'd like the actual data, which begins with an address (in hexadecimal), e.g. [ 8d]
. Filtering out to only lines with addresses, we get:
$ readelf -p .comment -p .note.gnu.gold-version $(which ja) | \
ja '{%/^\s*[[\sa-f0-9]*]\s*(.*$)/}{`0}'
[ 1] GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
[ 2c] GHC 9.10.1
[ 37] GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
[ 62] rustc version 1.78.0 (9b00956e5 2024-04-29)
[ c] GNU
[ 10] gold 1.16
To focus only on the data, not the address:
$ readelf -p .comment -p .note.gnu.gold-version $(which ja) | \
ja '.?{|`0 ~* 1 /^\s*[[\sa-f0-9]*]\s*(.*$)/}'
GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
GHC 9.10.1
GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
rustc version 1.78.0 (9b00956e5 2024-04-29)
GNU
gold 1.16
That has a spurious line GNU
; we filter for known compilers and linkers, viz.
$ readelf -p .comment -p .note.gnu.gold-version $(which ja) | \
ja '.?{%/clang|mold|gold|GCC|GHC|rustc/}{`0 ~* 1 /^\s*[[\sa-f0-9]*]\s*(.*$)/}'
GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
GHC 9.10.1
GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
rustc version 1.78.0 (9b00956e5 2024-04-29)
gold 1.16