Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect detection of Windows executable by gprconfig #152

Open
LordAro opened this issue Dec 11, 2024 · 1 comment
Open

Incorrect detection of Windows executable by gprconfig #152

LordAro opened this issue Dec 11, 2024 · 1 comment

Comments

@LordAro
Copy link

LordAro commented Dec 11, 2024

gprconfig uses the following to determine whether a file is a valid Windows executable

function Is_Windows_Executable (Filename : String) return Boolean is
type Byte is mod 256;
for Byte'Size use 8;
for Byte'Alignment use 1;
type Bytes is array (Positive range <>) of Byte;
Windows_Pattern : constant Bytes := (77, 90, 144, 0);
Fd : constant File_Descriptor := Open_Read (Filename, Binary);
B : Bytes (1 .. 4);
N_Read : Integer;
begin
N_Read := Read (Fd, B'Address, 4);
Close (Fd);
if N_Read < 4 then
return False;
else
if B = Windows_Pattern then
return True;
else
return False;
end if;
end if;
end Is_Windows_Executable;

specifically looking at the first 4 bytes of the file match using Windows_Pattern : constant Bytes := (77, 90, 144, 0);

This is typically works, but it's not actually correct - only MZ / 0x4d5a is required, the 3rd & 4th bytes are actually just e_cblp, or "Bytes on last page of file". It seems typically that's set to 0x90, but not exclusively. I'm not sure anything actually uses it.

However, I've just run into an issue where gprconfig refuses to recognise a compiler that was linked with lld where it's set to 0x78 (apparently the lld linker does actually set it?) (best not ask exactly why I'm doing this)

The correct method of determining a valid binary is to lookup the COFF File header at position 0x3c and then find the machine type - https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#coff-file-header-object-and-image

I implemented this routine in Perl a while back, which may prove of interest.

    my ($path) = @_;
    $path->open( "<:raw" );
    my @bytes = unpack( "C*", $path->read_n_bytes( 4 ) );
    my $arch;
    if( $bytes[ 0 ] == 0x4d && $bytes[ 1 ] == 0x5a )
    {
        # COFF binary (Windows)
        $path->seek_abs( 0x3c );
        my $header_pos = unpack( "L", $path->read_n_bytes( 4 ) );
        $path->seek_abs( $header_pos + 4 );
        my $machine = unpack( "S", $path->read_n_bytes( 2 ) );
        if( $machine == 0x14c ) # IMAGE_FILE_MACHINE_I386
        {
            $arch = 32;
        }
        elsif( $machine == 0x8664 ) # IMAGE_FILE_MACHINE_AMD64
        {
            $arch = 64;
        }
        else
        {
            print "Unknown machine type of COFF binary " . $path->get_absolute_name() . ": $machine\n";
        }
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant