Просмотр исходного кода

fcl-res: Mach-O fat binary support

Only for TMachOResourceReader. We always compile/generate a single architecture
binary, and then the programmer can combine those with lipo. So the writer does
not need fat binary support for common usage.

Resolves #39124
Jonas Maebe 3 лет назад
Родитель
Сommit
fa4e528576

+ 11 - 1
packages/fcl-res/src/machoconsts.pp

@@ -41,6 +41,8 @@ const
   MH_MAGIC_64 = $FEEDFACF;
   MH_CIGAM    = $CEFAEDFE;
   MH_CIGAM_64 = $CFFAEDFE;
+  FAT_MAGIC   = $CAFEBABE;
+  FAT_CIGAM   = $BEBAFECA;
 
   //Cpu types
   CPU_ARCH_ABI64     = $1000000;
@@ -53,9 +55,16 @@ const
   CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC or CPU_ARCH_ABI64;
 
   //Cpu subtypes
+  CPU_SUBTYPE_MASK        = tmach_cpu_subtype($ff000000);
+
   CPU_SUBTYPE_I386_ALL    = 3;
-  CPU_SUBTYPE_X86_64_ALL  = CPU_SUBTYPE_I386_ALL;
+  CPU_SUBTYPE_X86_64_ALL  = 3;
+  CPU_SUBTYPE_X86_64_ARCH1= 4;
+  CPU_SUBTYPE_X86_64_H    = 8; // Haswell feature subset
   CPU_SUBTYPE_POWERPC_ALL = 0;
+  CPU_SUBTYPE_POWERPC_7400 = 10;
+  CPU_SUBTYPE_POWERPC_7450 = 11;
+  CPU_SUBTYPE_POWERPC_970  = 100;
   CPU_SUBTYPE_ARM_ALL     = 0;
   CPU_SUBTYPE_ARM_V4T     = 5;
   CPU_SUBTYPE_ARM_V6      = 6;
@@ -64,6 +73,7 @@ const
   CPU_SUBTYPE_ARM_V7      = 9;
   CPU_SUBTYPE_ARM64_ALL   = 0;
   CPU_SUBTYPE_ARM64_V8    = 1;
+  CPU_SUBTYPE_ARM64E      = 2;
 
   //Mach-O object types
   MH_OBJECT      = $1;            // relocatable object file

+ 6 - 0
packages/fcl-res/src/machodefaulttarget.inc

@@ -16,21 +16,27 @@
   fMachineType:=mmtpowerpc; //default
   {$IFDEF CPUPOWERPC32}
   fMachineType:=mmtpowerpc;
+  fSubMachineType.fPpcSubType:=msmppc_all;
   {$ENDIF}
   {$IFDEF CPUPOWERPC64}
   fMachineType:=mmtpowerpc64;
+  fSubMachineType.fPpc64SubType:=msmppc64_all;
   {$ENDIF}
   {$IFDEF CPUI386}
   fMachineType:=mmti386;
+  fSubMachineType.f386SubType:=msm386_all;
   {$ENDIF}
   {$IFDEF CPUX86_64}
   fMachineType:=mmtx86_64;
+  fSubMachineType.fX64SubType:=msmx64_all;
   {$ENDIF}
   {$IFDEF CPUARM}
   fMachineType:=mmtarm;
+  fSubMachineType.fArmSubType:=msmarm_all;
   {$ENDIF}
   {$IFDEF CPUAARCH64}
   fMachineType:=mmtarm64;
+  fSubMachineType.fArm64SubType:=msmaarch64_all;
   {$ENDIF}
 
   fBits:=MACH_ERRBIT;

+ 109 - 25
packages/fcl-res/src/machoreader.pp

@@ -34,6 +34,7 @@ type
     fEndianess : integer;
     fOppositeEndianess : boolean;
     fMachineType : TMachOMachineType;
+    fSubMachineType : TMachoSubMachineType;
     fBits : integer;
     fHeader : TMachHdr;
     procedure SetDefaultTarget;
@@ -43,15 +44,19 @@ type
     function GetDescription : string; override;
     procedure Load(aResources : TResources; aStream : TStream); override;
     function CheckMagic(aStream : TStream) : boolean; override;
+
+    function FindBestFatArchOffset(aStream : TStream; switchEndian: boolean; fatheader: TMachFatHdr): int64;
   public
-    constructor Create; override;
+    constructor Create; override; overload;
+    constructor Create(AMachineType: TMachOMachineType; ASubMachineType: TMachoSubMachineType);
     destructor Destroy; override;
     property MachineType : TMachOMachineType read fMachineType;
+    property SubMachineType : TMachOSubMachineType read fSubMachineType;
   end;
 
 implementation
 
-uses machoconsts, resfactory, resourcetree, resdatastream, fpcrestypes;
+uses ctypes, machoconsts, resfactory, resourcetree, resdatastream, fpcrestypes;
 
 type
 
@@ -178,12 +183,47 @@ begin
 end;
 
 function TMachOResourceReader.ReadMachOHeader(aStream: TStream): boolean;
-var tmp : longword;
+var
+  fatArchOffset: int64;
+  tmp : longword;
+  magic: cuint32;
+  fathdr: TMachFatHdr;
 begin
   Result:=false;
 
   try
-    aStream.ReadBuffer(fHeader,sizeof(fHeader));
+    aStream.ReadBuffer(magic,sizeof(magic));
+  except
+    on e : EReadError do exit;
+  end;
+
+  case magic of
+    FAT_MAGIC,
+    FAT_CIGAM:
+      begin
+        fathdr.magic:=magic;
+        try
+          aStream.ReadBuffer((pbyte(@fathdr)+sizeof(magic))^,sizeof(fathdr)-sizeof(magic));
+        except
+          on e : EReadError do exit;
+        end;
+
+        fatArchOffset:=FindBestFatArchOffset(aStream,fathdr.magic=FAT_CIGAM,fathdr);
+        if fatArchOffset=-1 then
+          exit;
+        aStream.Seek(fatArchOffset,soBeginning);
+
+        try
+          aStream.ReadBuffer(magic,sizeof(magic));
+        except
+          on e : EReadError do exit;
+        end;
+      end;
+    end;
+
+  fheader.magic:=magic;
+  try
+    aStream.ReadBuffer((pbyte(@fHeader)+sizeof(magic))^,sizeof(fheader)-sizeof(magic));
   except
     on e : EReadError do exit;
   end;
@@ -193,7 +233,8 @@ begin
     MH_MAGIC_64 : begin fBits:=MACH_64BIT; fOppositeEndianess:=false; end;
     MH_CIGAM    : begin fBits:=MACH_32BIT; fOppositeEndianess:=true; end;
     MH_CIGAM_64 : begin fBits:=MACH_64BIT; fOppositeEndianess:=true; end
-    else exit;
+    else
+      exit;
   end;
   
   if fOppositeEndianess then
@@ -201,29 +242,23 @@ begin
       MACH_BIG_ENDIAN    : fEndianess:=MACH_LITTLE_ENDIAN;
       MACH_LITTLE_ENDIAN : fEndianess:=MACH_BIG_ENDIAN;
     end
-  else fEndianess:=fNativeEndianess;
+  else
+    fEndianess:=fNativeEndianess;
   
   if fOppositeEndianess then
-  begin
-    fHeader.magic:=SwapEndian(fHeader.magic);
-    fHeader.cputype:=SwapEndian(fHeader.cputype);
-    fHeader.cpusubtype:=SwapEndian(fHeader.cpusubtype);
-    fHeader.filetype:=SwapEndian(fHeader.filetype);
-    fHeader.ncmds:=SwapEndian(fHeader.ncmds);
-    fHeader.sizeofcmds:=SwapEndian(fHeader.sizeofcmds);
-    fHeader.flags:=SwapEndian(fHeader.flags);
-  end;
-  
-  case fHeader.cputype of
-    CPU_TYPE_I386      : fMachineType:=mmti386;
-    CPU_TYPE_X86_64    : fMachineType:=mmtx86_64;
-    CPU_TYPE_POWERPC   : fMachineType:=mmtpowerpc;
-    CPU_TYPE_POWERPC64 : fMachineType:=mmtpowerpc64;
-    CPU_TYPE_ARM       : fMachineType:=mmtarm;
-    CPU_TYPE_ARM64     : fMachineType:=mmtarm64
-    else exit;
-  end;
+    begin
+      fHeader.magic:=SwapEndian(fHeader.magic);
+      fHeader.cputype:=SwapEndian(fHeader.cputype);
+      fHeader.cpusubtype:=SwapEndian(fHeader.cpusubtype);
+      fHeader.filetype:=SwapEndian(fHeader.filetype);
+      fHeader.ncmds:=SwapEndian(fHeader.ncmds);
+      fHeader.sizeofcmds:=SwapEndian(fHeader.sizeofcmds);
+      fHeader.flags:=SwapEndian(fHeader.flags);
+    end;
   
+  if not MachOMachineTypesToPas(fHeader.cpuType,fheader.cpusubtype,fMachineType,fSubMachineType) then
+    exit;
+
   //64-bit mach-o files have 4 bytes of padding after the header
   if fBits=MACH_64BIT then
     try
@@ -272,6 +307,48 @@ begin
   Result:=ReadMachOHeader(aStream);
 end;
 
+function TMachOResourceReader.FindBestFatArchOffset(aStream : TStream; switchEndian: boolean; fatheader: TMachFatHdr): int64;
+var
+  fatarchs: array of TMachFarArch;
+  machPas: TMachOMachineType;
+  machSubPas: TMachoSubMachineType;
+  i: cuint32;
+  bestCompatibility, newCompatibility: TMachOSubMachineTypeCompatible;
+begin
+  result:=-1;
+  if switchEndian then
+    begin
+      fatheader.magic:=SwapEndian(fatheader.magic);
+      fatheader.nfatarch:=SwapEndian(fatheader.nfatarch);
+    end;
+  setlength(fatarchs,fatheader.nfatarch);
+  try
+    aStream.read(fatarchs[0], fatheader.nfatarch * sizeof(fatarchs[0]));
+  except
+    on e : EReadError do
+      raise EResourceReaderUnexpectedEndOfStreamException.Create('');
+  end;
+  bestCompatibility:=smc_incompatible;
+  for i:=0 to fatheader.nfatarch-1 do
+    begin
+      if switchEndian then
+        begin
+          fatarchs[i].cputype:=swapendian(fatarchs[i].cputype);
+          fatarchs[i].cpusubtype:=swapendian(fatarchs[i].cpusubtype);
+          fatarchs[i].offset:=swapendian(fatarchs[i].offset);
+          fatarchs[i].size:=swapendian(fatarchs[i].size);
+          fatarchs[i].align:=swapendian(fatarchs[i].align);
+        end;
+      if not MachOMachineTypesToPas(fatarchs[i].cputype,fatarchs[i].cpusubtype,machPas,machSubPas) then
+        continue;
+      if machPas<>fMachineType then
+        continue;
+      newCompatibility:=MachOSubMachineTypesEqual(machPas,fSubMachineType,machSubPas);
+      if newCompatibility>bestCompatibility then
+        result:=fatarchs[i].offset;
+    end;
+end;
+
 constructor TMachOResourceReader.Create;
 begin
   fExtensions:='.o .or';
@@ -279,6 +356,13 @@ begin
   SetDefaultTarget;
 end;
 
+constructor TMachOResourceReader.Create(AMachineType: TMachOMachineType; ASubMachineType: TMachoSubMachineType);
+  begin
+    Create;
+    fMachineType:=AMachineType;
+    fSubMachineType:=ASubMachineType;
+  end;
+
 destructor TMachOResourceReader.Destroy;
 begin
 

+ 235 - 80
packages/fcl-res/src/machotypes.pp

@@ -19,141 +19,296 @@ unit machotypes;
 
 interface
 
+uses
+  ctypes;
+
 {$packrecords c}
 
 type
   TMachOMachineType = (mmtpowerpc, mmtpowerpc64, mmti386, mmtx86_64, mmtarm, mmtarm64);
-  TMachOSubMachineTypePowerPC = (msmppc_all);
+  TMachOSubMachineTypePowerPC = (msmppc_all, msmppc_7400, msmppc_7450, msmppc_970);
   TMachOSubMachineTypePowerPC64 = (msmppc64_all);
   TMachOSubMachineType386 = (msm386_all);
-  TMachOSubMachineTypex64 = (msmx64_all);
+  TMachOSubMachineTypex64 = (msmx64_all, msmx64_haswell);
   TMachOSubMachineTypeArm = (msmarm_all,msmarm_v4t,msmarm_v6,msmarm_v5tej,msmarm_xscale,msmarm_v7);
-  TMachOSubMachineTypeAarch64 = (msmaarch64_all);
+  TMachOSubMachineTypeAarch64 = (msmaarch64_all, msmaarch64_v8, msmaarch64_e);
   TSegSectName = array[0..15] of char;
 
+  TMachOSubMachineType = record
+    case TMachOMachineType of
+      msmppc_all: (fPpcSubType: TMachOSubMachineTypePowerPC);
+      msmppc64_all: (fPpc64SubType: TMachOSubMachineTypePowerPC64);
+      msm386_all: (f386SubType: TMachOSubMachineType386);
+      msmx64_all: (fX64SubType: TMachOSubMachineTypex64);
+      mmtarm: (fArmSubType: TMachOSubMachineTypeArm);
+      mmtarm64: (fArm64SubType: TMachOSubMachineTypeAarch64);
+  end;
+
+  tmach_integer = cint;
+  tmach_cpu_type = tmach_integer;
+  tmach_cpu_subtype = tmach_integer;
+  tmach_cpu_threadtype = tmach_integer;
+  tmach_vm_prot = cint;
+
 type
+  TMachFatHdr = record
+    magic: cuint32;
+    nfatarch: cuint32;
+  end;
+
+  TMachFarArch = record
+    cputype: tmach_cpu_type;
+    cpusubtype: tmach_cpu_subtype;
+    offset: cuint32;
+    size: cuint32;
+    align: cuint32;
+  end;
+
   TMachHdr = record
-    magic : longword;
-    cputype : longint;
-    cpusubtype : longint;
-    filetype : longword;
-    ncmds : longword;
-    sizeofcmds : longword;
-    flags : longword;
+    magic: cuint32;
+    cputype: tmach_cpu_type;
+    cpusubtype: tmach_cpu_subtype;
+    filetype: cuint32;
+    ncmds: cuint32;
+    sizeofcmds: cuint32;
+    flags: cuint32;
+    {$IFDEF CPU64}
+    reserved: cuint32;
+    {$ENDIF}
   end;
 
   TLoadCommand = record
-    cmd : longword;
-    cmdsize : longword;
+    cmd: cuint32;
+    cmdsize: cuint32;
   end;
 
   //note: all commands don't include first two longwords
 
   TSegmentCommand32 = record
     name     : TSegSectName;
-    vmaddr   : longword;
-    vmsize   : longword;
-    fileoff  : longword;
-    filesize : longword;
-    maxprot  : longint;
-    initprot : longint;
-    nsects   : longword;
-    flags    : longword;
+    vmaddr   : cuint32;
+    vmsize   : cuint32;
+    fileoff  : cuint32;
+    filesize : cuint32;
+    maxprot  : tmach_vm_prot;
+    initprot : tmach_vm_prot;
+    nsects   : cuint32;
+    flags    : cuint32;
   end;
 
   TSegmentCommand64 = record
     name     : TSegSectName;
-    vmaddr   : qword;
-    vmsize   : qword;
-    fileoff  : qword;
-    filesize : qword;
-    maxprot  : longint;
-    initprot : longint;
-    nsects   : longword;
-    flags    : longword;
+    vmaddr   : cuint64;
+    vmsize   : cuint64;
+    fileoff  : cuint64;
+    filesize : cuint64;
+    maxprot  : tmach_vm_prot;
+    initprot : tmach_vm_prot;
+    nsects   : cuint32;
+    flags    : cuint32;
   end;
   
   TSection32 = record
     sectname : TSegSectName;
     segname  : TSegSectName;
-    addr : longword;
-    size : longword;
-    offset : longword;
-    align : longword;
-    reloff : longword;
-    nreloc : longword;
-    flags : longword;
-    reserved1 : longword;
-    reserved2 : longword;
+    addr : cuint32;
+    size : cuint32;
+    offset : cuint32;
+    align : cuint32;
+    reloff : cuint32;
+    nreloc : cuint32;
+    flags : cuint32;
+    reserved1 : cuint32;
+    reserved2 : cuint32;
   end;
 
   TSection64 = record
     sectname : TSegSectName;
     segname  : TSegSectName;
-    addr : qword;
-    size : qword;
-    offset : longword;
-    align : longword;
-    reloff : longword;
-    nreloc : longword;
-    flags : longword;
-    reserved1 : longword;
+    addr : cuint64;
+    size : cuint64;
+    offset : cuint32;
+    align : cuint32;
+    reloff : cuint32;
+    nreloc : cuint32;
+    flags : cuint32;
+    reserved1 : cuint32;
     reserved2 : longword;
-    reserved3 : longword;
+    reserved3 : cuint32;
   end;
 
   TSymtabCommand = record
-    symoff : longword;
-    nsyms : longword;
-    stroff : longword;
-    strsize : longword;
+    symoff : cuint32;
+    nsyms : cuint32;
+    stroff : cuint32;
+    strsize : cuint32;
   end;
   
   TDySymtabCommand = record
-    ilocalsym : longword;
-    nlocalsym : longword;
-    iextdefsym : longword;
-    nextdefsym : longword;
-    iundefsym : longword;
-    nundefsym : longword;
-    tocoff : longword;
-    ntoc : longword;
-    modtaboff : longword;
-    nmodtab : longword;
-    extrefsymoff : longword;
-    nextrefsyms : longword;
-    indirectsymoff : longword;
-    nindirectsyms : longword;
-    extreloff : longword;
-    nextrel : longword;
-    locreloff : longword;
-    nlocrel : longword;
+    ilocalsym : cuint32;
+    nlocalsym : cuint32;
+    iextdefsym : cuint32;
+    nextdefsym : cuint32;
+    iundefsym : cuint32;
+    nundefsym : cuint32;
+    tocoff : cuint32;
+    ntoc : cuint32;
+    modtaboff : cuint32;
+    nmodtab : cuint32;
+    extrefsymoff : cuint32;
+    nextrefsyms : cuint32;
+    indirectsymoff : cuint32;
+    nindirectsyms : cuint32;
+    extreloff : cuint32;
+    nextrel : cuint32;
+    locreloff : cuint32;
+    nlocrel : cuint32;
   end;
   
   TNList32 = record
-    strx : longword;
-    _type : byte;
-    sect : byte;
-    desc : word;
-    value : longword;
+    strx : cuint32;
+    _type : cuint8;
+    sect : cuint8;
+    desc : cuint16;
+    value : cuint32;
   end;
   PNList32 = ^TNList32;
   
   TNList64 = record
-    strx : longword;
-    _type : byte;
-    sect : byte;
-    desc : word;
-    value : qword;
+    strx : cuint32;
+    _type : cuint8;
+    sect : cuint8;
+    desc : cuint16;
+    value : cuint64;
   end;
   PNList64 = ^TNList64;
 
   TRelocationInfo = record
-    address : longword;
-    flags : longword;
+    address : cuint32;
+    flags : cuint32;
   end;
   PRelocationInfo = ^TRelocationInfo;
 
+  TMachOSubMachineTypeCompatible = (smc_incompatible, smc_compatible, smc_exact);
+
+  function MachOMachineTypesToPas(mach: tmach_cpu_type; sub: tmach_cpu_subtype; out machPas: TMachOMachineType; out subPas: TMachOSubMachineType): boolean;
+  function MachOSubMachineTypesEqual(mach: TMachOMachineType; const wantedSubType, fileSubType: TMachOSubMachineType): TMachOSubMachineTypeCompatible;
+
 implementation
 
+  uses
+    machoconsts;
+
+  function MachOMachineTypesToPas(mach: tmach_cpu_type; sub: tmach_cpu_subtype; out machPas: TMachOMachineType; out subPas: TMachOSubMachineType): boolean;
+    begin
+      result:=true;
+      case mach of
+        CPU_TYPE_POWERPC:
+          begin
+            machpas:=mmtpowerpc;
+            case sub and not(CPU_SUBTYPE_MASK) of
+              CPU_SUBTYPE_POWERPC_7400:
+                subPas.fPpcSubType:=msmppc_7400;
+              CPU_SUBTYPE_POWERPC_7450:
+                subPas.fPpcSubType:=msmppc_7450;
+              CPU_SUBTYPE_POWERPC_970:
+                subPas.fPpcSubType:=msmppc_970;
+              else
+                subPas.fPpcSubType:=msmppc_all;
+            end;
+            exit;
+          end;
+        CPU_TYPE_POWERPC64:
+          begin
+            machpas:=mmtpowerpc64;
+            subPas.fPpc64SubType:=msmppc64_all;
+            exit;
+          end;
+        CPU_TYPE_I386:
+          begin
+            machpas:=mmti386;
+            subPas.f386SubType:=msm386_all;
+            exit;
+          end;
+        CPU_TYPE_X86_64:
+          begin
+            machpas:=mmtx86_64;
+            case sub and not(CPU_SUBTYPE_MASK) of
+              CPU_SUBTYPE_X86_64_H:
+                subPas.fX64SubType:=msmx64_haswell;
+              else
+                subPas.fX64SubType:=msmx64_all;
+            end;
+            exit;
+          end;
+        CPU_TYPE_ARM:
+          begin
+            machpas:=mmtarm;
+            subPas.fArmSubType:=msmarm_all;
+            exit;
+          end;
+        CPU_TYPE_ARM64     :
+          begin
+            machpas:=mmtarm64;
+            case sub and not(CPU_SUBTYPE_MASK) of
+              CPU_SUBTYPE_ARM64_V8:
+                subPas.fArm64SubType:=msmaarch64_v8;
+              CPU_SUBTYPE_ARM64E:
+                subPas.fArm64SubType:=msmaarch64_e;
+              else
+                subPas.fArm64SubType:=msmaarch64_all;
+            end;
+            exit;
+          end;
+      end;
+      result:=false;
+    end;
+
+
+  function MachOSubMachineTypesEqual(mach: TMachOMachineType; const wantedSubType, fileSubType: TMachOSubMachineType): TMachOSubMachineTypeCompatible;
+    begin
+      result:=smc_incompatible;
+      case mach of
+        mmtpowerpc:
+          begin
+            if wantedSubType.fPpcSubType=fileSubType.fPpcSubType then
+              exit(smc_exact)
+            else if wantedSubType.fPpcSubType>fileSubType.fPpcSubType then
+              exit(smc_compatible);
+          end;
+        mmtpowerpc64:
+          begin
+            if wantedSubType.fPpc64SubType=fileSubType.fPpc64SubType then
+              exit(smc_exact)
+          end;
+        mmti386:
+          begin
+            if wantedSubType.f386SubType=fileSubType.f386SubType then
+              exit(smc_exact)
+          end;
+        mmtx86_64:
+          begin
+            if wantedSubType.fX64SubType=fileSubType.fX64SubType then
+              exit(smc_exact)
+            else if wantedSubType.fX64SubType>fileSubType.fX64SubType then
+              exit(smc_compatible);
+          end;
+        mmtarm:
+          begin
+            if wantedSubType.fArmSubType=fileSubType.fArmSubType then
+              exit(smc_exact)
+            else if wantedSubType.fArmSubType>fileSubType.fArmSubType then
+              exit(smc_compatible);
+          end;
+        mmtarm64:
+          begin
+            if wantedSubType.fArm64SubType=fileSubType.fArm64SubType then
+              exit(smc_exact)
+            else if (wantedSubType.fArm64SubType in [msmaarch64_all,msmaarch64_v8]) = (fileSubType.fArm64SubType in [msmaarch64_all,msmaarch64_v8]) then
+              exit(smc_exact)
+            // msmaarch64_e means pointer authentication etc which are different from plain ARMv8 code
+          end;
+      end;
+    end;
+
 end.

+ 3 - 13
packages/fcl-res/src/machowriter.pp

@@ -31,16 +31,6 @@ type
 
   { TMachOResourceWriter }
 
-  TMachoSubMachineType = record
-    case TMachOMachineType of
-      msmppc_all: (fPpcSubType: TMachOSubMachineTypePowerPC);
-      msmppc64_all: (fPpc64SubType: TMachOSubMachineTypePowerPC64);
-      msm386_all: (f386SubType: TMachOSubMachineType386);
-      msmx64_all: (fX64SubType: TMachOSubMachineTypex64);
-      mmtarm: (fArmSubType: TMachOSubMachineTypeArm);
-      mmtarm64: (fArm64SubType: TMachOSubMachineTypeAarch64);
-  end;
-
   TMachOResourceWriter = class(TAbstractResourceWriter)
   private
     fExtensions : string;
@@ -505,14 +495,14 @@ end;
 
 procedure TAbstractMachOSubWriter.FixHeader(aStream: TStream);
 const
-  ppcsm2int: array[TMachOSubMachineTypePowerPC] of longint = (CPU_SUBTYPE_POWERPC_ALL);
+  ppcsm2int: array[TMachOSubMachineTypePowerPC] of longint = (CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_POWERPC_7400, CPU_SUBTYPE_POWERPC_7450, CPU_SUBTYPE_POWERPC_970);
   ppc64sm2int: array[TMachOSubMachineTypePowerPC64] of longint = (CPU_SUBTYPE_POWERPC_ALL);
   i386sm2int: array[TMachOSubMachineType386] of longint = (CPU_SUBTYPE_I386_ALL);
-  x86_64sm2int: array[TMachOSubMachineTypex64] of longint = (CPU_SUBTYPE_X86_64_ALL);
+  x86_64sm2int: array[TMachOSubMachineTypex64] of longint = (CPU_SUBTYPE_X86_64_ALL, CPU_SUBTYPE_X86_64_H);
   armsm2int: array[TMachOSubMachineTypeArm] of longint = (CPU_SUBTYPE_ARM_ALL,
     CPU_SUBTYPE_ARM_V4T,CPU_SUBTYPE_ARM_V6,CPU_SUBTYPE_ARM_V5TEJ,
     CPU_SUBTYPE_ARM_XSCALE,CPU_SUBTYPE_ARM_V7);
-  arm64sm2int: array[TMachOSubMachineTypeAarch64] of longint = (CPU_SUBTYPE_ARM64_ALL);
+  arm64sm2int: array[TMachOSubMachineTypeAarch64] of longint = (CPU_SUBTYPE_ARM64_ALL, CPU_SUBTYPE_ARM64_V8, CPU_SUBTYPE_ARM64E);
 begin
   aStream.Position:=0;
   case fMachineType of