#!/usr/bin/perl -w my $a; if ($#ARGV==2 && $ARGV[0] eq '-a') { shift; $a=shift } !$#ARGV or die "Usage: $0 [-a] \n"; open F, '<', $ARGV[0] or die "$0: can't read $ARGV[0]: $!\n"; my $header; my $hlen = sysread F, $header, 56; defined $hlen or die "$0: can't read $ARGV[0]: $!\n"; $hlen==56 or die "$0: $ARGV[0] not an ELF: only $hlen bytes long\n"; sub elf() { my ($word, $end, $version, $os, $abi, $isa) = unpack('xxxxCCCCCxxxxxxxxxv', $header); $version==1 or return "invalid"; my $id=sprintf("%d:%s:%x", 16*(1<<$word), substr("-lb",$end,1), $isa); my $wo32=substr("xVN",$end,1); my $flags_offset=0x18+(6<<$word); my $flags=unpack("x$flags_offset$wo32",$header); my %elf_arch=( "64:l:9026" => "alpha", "64:l:3e" => "amd64", "32:l:c3" => "arc", "32:l:28" => "arm", "64:l:b7" => "arm64", "32:l:b7" => "arm64ilp32", "32:b:f00" => "hppa", "64:b:f00" => "hppa64", "32:l:3" => "i386", "64:l:32" => "ia64", "64:l:102" => "loong64", "32:b:400" => "m68k", "32:b:800" => "mips", "64:b:800" => "mips64", "64:l:8" => "mips64el", "32:l:8" => "mipsel", "32:b:800" => "mips", "32:l:71" => "nios2", "32:b:5c00" => "or1k", "32:b:1400" => "powerpc", "64:b:1500" => "ppc64", "64:l:15" => "ppc64el", "64:l:f3" => "riscv64", "64:b:1600" => "s390x", "32:l:2a" => "sh4", "32:b:200" => "sparc", "64:b:2b00" => "sparc64", "32:l:3e" => "x32", ); $_=$elf_arch{$id}//"unknown"; if (/^mips/) { my $rel=$flags>>28&0xf; if ($rel==10) { s/mips64/mips64r6/} elsif ($rel==9) { s/mips/mipsr6/} elsif ($rel==2 && $word==1) { s/mips/mipsn32/} } if ($os==9) { $_="kfreebsd-$_" } elsif ($os==4) { $_="hurd-$_" } elsif ($os && $os!=3) # Linux is 3 in theory but almost always 0 { return "unknown" }; $_ } sub pe() { sysseek F, 0x3c, 0; $hlen = sysread F, $_, 4; defined $hlen or return die "$0: can't read $ARGV[0]: $!\n"; $_=unpack 'V'; $_>0 and sysseek(F, $_, 0) and sysread(F, $_, 4)==4 and $_ eq "PE\0\0" and sysread(F, $_, 2)==2 or return 'invalid'; $_=unpack 'v'; my %pe_arch=( 0x0 => 'pe-universal', 0x1d3 => 'win-am33', 0x8664 => 'win64', 0x1c0 => 'win-arm', 0xaa64 => 'win-arm64', 0x1c4 => 'win-armnt', # ARM Thumb-2 little endian 0xebc => 'ebc', # EFI byte code 0x14c => 'win32', 0x200 => 'win-ia64', 0x9041 => 'win-m32r', 0x266 => 'win-mips16', 0x366 => 'win-mipsfpu', 0x466 => 'win-mipsfpu16', 0x1f0 => 'win-powerpc', 0x1f1 => 'win-powerpcfp', 0x166 => 'win-r4000', 0x5032 => 'win-riscv32', 0x5064 => 'win-riscv64', 0x5128 => 'win-riscv128', 0x1a2 => 'win-sh3', 0x1a3 => 'win-sh3dsp', 0x1a6 => 'win-sh4', 0x1a8 => 'win-sh4', 0x1c2 => 'win-thumb', 0x169 => 'win-wcemipsv2', ); return $pe_arch{$_}//'pe-unknown'; } my $ea = (unpack('N', $header)==0x7f454c46) ? elf : (substr($header,0,2) eq 'MZ') ? pe : "invalid"; defined($a) or print("$ea\n"), exit 0; exit 0 if $ea eq $a; # Try unmangled first. $a=~s/^musl-//; # These usually have unmarked binaries. $a=~s/^hurd-//; $a=~s/^illumos-//; $a=~s/^solaris-//; $a=~s/^linux-//; my %aliases=( 'arm' => ['armel', 'armhf'], 'powerpc' => ['powerpcspe'], 'sh4' => ['sh3'], ); exit 0 if $ea eq $a; exit 1 unless defined $aliases{$ea}; exit !grep { $_ eq $a } @{$aliases{$ea}}