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