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