File: fpimgreadermachofile.pas

package info (click to toggle)
lazarus 2.2.6%2Bdfsg2-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 219,980 kB
  • sloc: pascal: 1,944,919; xml: 357,634; makefile: 270,608; cpp: 57,115; sh: 3,249; java: 609; perl: 297; sql: 222; ansic: 137
file content (136 lines) | stat: -rw-r--r-- 3,267 bytes parent folder | download
1
2
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
unit FpImgReaderMachoFile;

{$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.