| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 
 | unit FpImgReaderMachoFile;
{$T-} // TODO: Fix compilation with -Sy.
{$mode objfpc}{$H+}
interface
//todo: powerpc, x86_64
uses
  Classes, SysUtils, macho, FpImgReaderBase,
  FpDbgCommon;
type
  TMachOsection = class(TObject)
    is32   : Boolean;
    sec32  : section;
    sec64  : section_64;
  end;
  { TMachOFile }
  TMachOFile = class(TObject)
  private
    cmdbuf    : array of byte;
    FTargetInfo   : TTargetDescriptor;
  public
    header    : mach_header;
    commands  : array of pload_command;
    sections  : TFPList;
    UUID      : TGuid;
    constructor Create;
    destructor Destroy; override;
    function  LoadFromFile(ALoader: TDbgFileLoader): Boolean;
    property TargetInfo: TTargetDescriptor read FTargetInfo;
  end;
implementation
{ TMachOFile }
constructor TMachOFile.Create;
begin
  sections := TFPList.Create;
end;
destructor TMachOFile.Destroy;
var
  i : integer;
begin
  for i := 0 to sections.Count - 1 do TMachOsection(sections[i]).Free;
  sections.Free;
  inherited Destroy;
end;
function TMachOFile.LoadFromFile(ALoader: TDbgFileLoader): Boolean;
var
  i   : Integer;
  j   : Integer;
  ofs : Integer;
  sc32: psection;
  sc64: psection_64;
  idcm: puuid_command;
  s   : TMachOsection;
  hs  : integer;
  i64 : boolean;
begin
  Result :=  ALoader.Read(0, sizeof(header), @header) = sizeof(header);
  if not Result then Exit;
  i64 := (header.magic = MH_CIGAM_64) or (header.magic = MH_MAGIC_64);
  Result := (header.magic = MH_MAGIC) or (header.magic = MH_CIGAM) or i64;
  if i64 then
  begin
    hs := sizeof(mach_header_64);
    FTargetInfo.bitness := b64;
  end
  else
  begin
    hs := SizeOf(mach_header);
    FTargetInfo.bitness := b32;
  end;
  case header.cputype of
    CPU_TYPE_I386       : FTargetInfo.MachineType := mt386;
    CPU_TYPE_ARM        : FTargetInfo.MachineType := mtARM;
    CPU_TYPE_SPARC      : FTargetInfo.MachineType := mtSPARC;
    //CPU_TYPE_ALPHA      : FTargetInfo.MachineType := mtALPHA;
    CPU_TYPE_POWERPC    : FTargetInfo.MachineType := mtPPC;
    CPU_TYPE_POWERPC64  : FTargetInfo.MachineType := mtPPC;
    CPU_TYPE_X86_64     : FTargetInfo.MachineType := mtX86_64;
    CPU_TYPE_ARM64      : FTargetInfo.MachineType := mtARM;
  else
    FTargetInfo.machineType := mtNone;
  end;
  SetLength(cmdbuf, header.sizeofcmds);
  ALoader.Read(hs, header.sizeofcmds, @cmdbuf[0]);
  SetLength(commands, header.ncmds);
  ofs := 0;
  for i := 0 to header.ncmds - 1 do begin
    commands[i] := @cmdbuf[ofs];
    if commands[i]^.cmd = LC_SEGMENT then begin
      sc32 := @cmdbuf[ofs+sizeof(segment_command)];
      for j := 0 to psegment_command(commands[i])^.nsects- 1 do begin
        s := TMachOSection.Create;
        s.is32:=true;
        s.sec32:=sc32^;
        sections.add(s);
        inc(sc32);
      end;
    end
    else if commands[i]^.cmd = LC_SEGMENT_64 then begin
      sc64 := @cmdbuf[ofs+sizeof(segment_command_64)];
      for j := 0 to psegment_command_64(commands[i])^.nsects- 1 do begin
        s := TMachOSection.Create;
        s.is32:=False;
        s.sec64:=sc64^;
        sections.add(s);
        inc(sc64);
      end;
    end
    else if commands[i]^.cmd = LC_UUID then begin
      idcm := @cmdbuf[ofs];
      UUID:=PGuid(@(idcm^.uuid))^;
    end;
    inc(ofs, commands[i]^.cmdsize);
  end;
end;
end.
 |