How to determine if dll file was compiled as x64 or x86 bit using either Delphi or Lazarus
Asked Answered
F

2

8

Using either Delphi 2007+ or Lazarus(Win64) I'm looking for a way to determine if a dll is compiled as x64 or x86?

Farrish answered 1/5, 2010 at 1:5 Comment(1)
I've found the following information but haven't had time to assimilate it: tech-archive.net/Archive/Development/… This link: delphidabbler.com/articles?article=8&part=2 mentioned in the previous linked article provides Delphi source to parse the file header that can identify 16 & 32 bit, but not 64. The code can run on Delphi 2007 as is but not on Delphi2010 or Lazarus - at least not without more modifications than I had time or experience for.Farrish
G
18

You should read and parse PE header.

Like this:

function Isx64(const Strm: TStream): Boolean;
const
  IMAGE_FILE_MACHINE_I386     = $014c; // Intel x86
  IMAGE_FILE_MACHINE_IA64     = $0200; // Intel Itanium Processor Family (IPF)
  IMAGE_FILE_MACHINE_AMD64    = $8664; // x64 (AMD64 or EM64T)
  // You'll unlikely encounter the things below:
  IMAGE_FILE_MACHINE_R3000_BE = $160;  // MIPS big-endian
  IMAGE_FILE_MACHINE_R3000    = $162;  // MIPS little-endian, 0x160 big-endian
  IMAGE_FILE_MACHINE_R4000    = $166;  // MIPS little-endian
  IMAGE_FILE_MACHINE_R10000   = $168;  // MIPS little-endian
  IMAGE_FILE_MACHINE_ALPHA    = $184;  // Alpha_AXP }
  IMAGE_FILE_MACHINE_POWERPC  = $1F0;  // IBM PowerPC Little-Endian
var
  Header: TImageDosHeader;
  ImageNtHeaders: TImageNtHeaders;
begin
  Strm.ReadBuffer(Header, SizeOf(Header));
  if (Header.e_magic <> IMAGE_DOS_SIGNATURE) or
     (Header._lfanew = 0) then
    raise Exception.Create('Invalid executable');
  Strm.Position := Header._lfanew;

  Strm.ReadBuffer(ImageNtHeaders, SizeOf(ImageNtHeaders));
  if ImageNtHeaders.Signature <> IMAGE_NT_SIGNATURE then
    raise Exception.Create('Invalid executable');

  Result := ImageNtHeaders.FileHeader.Machine <> IMAGE_FILE_MACHINE_I386;
end;
Grow answered 1/5, 2010 at 7:24 Comment(3)
Thanks for the response. Unfortunately this would required JCL to work. I have not added JCL to my Delphi 2007 but may if it looks like the only expedient solution.Farrish
Your updated version works just fine in Delphi 2007 and Delphi 2010. An elegant solution - thank you.Farrish
Note that these constants are in unit Windows on FPC. (at least in 2.4.0+ don't know about older ones)Uncloak
S
6

You could use JclPeImage from the JCL. The following app shows how to do it.


program Isx64ImageTest;

{$APPTYPE CONSOLE}

uses
  SysUtils, JclWin32, JclPEImage;

var
  PEImage: TJclPeImage;
begin
  PEImage := TJclPeImage.Create;
  try
    //usage is "Isx64ImageTest filename"
    PEImage.FileName := ParamStr(1);
    //print the machine value as string
    WriteLn(Format('Machine value of image %s is %s',
      [PEImage.FileName, PEImage.HeaderValues[JclPeHeader_Machine]]));
    //check for a special machine value
    case PEImage.LoadedImage.FileHeader^.FileHeader.Machine of
      IMAGE_FILE_MACHINE_I386:  begin end;
      IMAGE_FILE_MACHINE_AMD64: begin end;
      else
      begin
      end;
    end;
  finally
    PEImage.Free;
  end;
end.
Salomo answered 1/5, 2010 at 15:37 Comment(2)
If you're using JCL - there is more simpler approach - by using PeMapImgTarget function or PEImage.Target property (in your example). No need to analyze headers by yourself.Grow
Not using JCL yet, may eventually do so. I've been trying to mirror my Delphi2007 and Delphi2010 components because I've been planning on migrating to Delphi2010. Is JCL available for Delphi2010?Farrish

© 2022 - 2024 — McMap. All rights reserved.